Java基础-集合框架-ArrayList源码分析
一、JDK中ArrayList是如何实现的
1、先看下ArrayList从上而下的层次图:
说明:
从图中可以看出,ArrayList只是最下层的实现类,集合的规则和扩展都是AbstractList、List、Collection等上层的接口所设定的,而ArrayList实现或继承了上层的规则,然后重新或扩展来处理集合中的数据。
2、看看接口:Iterable<E>中都定义了那些规则?
JDK1.8中的源码:
1 package java.lang; 2 3 import java.util.Iterator; 4 import java.util.Objects; 5 import java.util.Spliterator; 6 import java.util.Spliterators; 7 import java.util.function.Consumer; 8 public interface Iterable<T> {//实现这个接口允许对象成为 "foreach" 语句的目标。 9 Iterator<T> iterator(); 10 default void forEach(Consumer<? super T> action) { 11 Objects.requireNonNull(action); 12 for (T t : this) { 13 action.accept(t); 14 } 15 } 16 default Spliterator<T> spliterator() { 17 return Spliterators.spliteratorUnknownSize(iterator(), 0); 18 } 19 }
这里说明一下:
(1)Consumer<? super T> action 可以理解为:实现了Consumer接口的实现类对象。
(2)accept(T t) T 是每一次forEach方法处理的数据类型,t是数据
(3)spliterator():Spliterator
(splitable iterator可分割迭代器)接口是Java为了并行遍历数据源中的元素而设计的迭代器。也就是收JDK1.8版本已经支持多核并发处理集合中的数据了,你只需要告诉JDK你要做什么并行任务,关注业务本身,至于如何并行,怎么并行效率最高,就交给JDK自己去思考和优化速度了。
简单举个forEach的例子:
1 package com.xfwl.test; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 import java.util.function.Consumer; 6 @SuppressWarnings("unchecked") 7 public class Test2 { 8 public static void main(String[] args) { 9 List alist=new ArrayList(); 10 alist.add("1"); 11 alist.forEach(new T()); 12 } 13 /** 14 * Consumer接口测试实现类T 15 * @param <E> 16 */ 17 static class T implements Consumer{ 18 public T(){} 19 public void accept(Object e) { 20 System.out.println("当前数据:"+e); 21 } 22 public Consumer andThen(Consumer after) { 23 // TODO Auto-generated method stub 24 return null; 25 } 26 } 27 }
运行结果:
当前数据:1
总结一下:
(1)接口Iterable,定义了遍历集合中的数据的方法:forEach(),这个方法需要一个实现了Consumer接口的参数;
(2)接口Iterable,定义了一个可以实现并发的迭代器,具体如何实现和优化交给jdk自己处理,我们只负责使用集合即可。
3、看看接口:Collection<E>中定义了那些规则?
JDK1.8中的源码:
1 package java.util; 2 import java.util.function.Predicate; 3 import java.util.stream.Stream; 4 import java.util.stream.StreamSupport; 5 6 public interface Collection<E> extends Iterable<E> { 7 int size(); //获取集合元素总数 8 boolean isEmpty(); //判断集合是否非空 9 boolean contains(Object o); //判断集合是否包含指定元素 10 Iterator<E> iterator(); //获取迭代器 11 Object[] toArray(); //把集合转化成Object类型数组对象 12 <T> T[] toArray(T[] a); //把集合转化成指定T类型数组对象 13 boolean add(E e); //添加数据到集合 14 boolean remove(Object o); //从集合中移除数据 15 boolean containsAll(Collection<?> c); //集合是否包含另一个集合 16 boolean addAll(Collection<? extends E> c); //集合添加另外一个集合 17 boolean removeAll(Collection<?> c); //集合中移除另外一个集合中的内容 18 default boolean removeIf(Predicate<? super E> filter) {//JDK1.8开始加入的方法,按指定条件移除集合中的信息 19 Objects.requireNonNull(filter); 20 boolean removed = false; 21 final Iterator<E> each = iterator(); 22 while (each.hasNext()) { 23 if (filter.test(each.next())) { 24 each.remove(); 25 removed = true; 26 } 27 } 28 return removed; 29 } 30 boolean retainAll(Collection<?> c); //移除此 collection 中未包含在指定 collection 中的所有元素 31 void clear(); //清除集合中的信息 32 boolean equals(Object o); //比较此 collection 与指定对象是否相等。 33 int hashCode(); //返回此 collection 的哈希码值。 34 @Override 35 default Spliterator<E> spliterator() { //JDK1.8开始新加入的方法,返回当前集合的并发迭代器 36 return Spliterators.spliterator(this, 0); 37 } 38 default Stream<E> stream() { //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据 39 return StreamSupport.stream(spliterator(), false);//返回的流是顺序的 40 } 41 default Stream<E> parallelStream() { //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据 42 return StreamSupport.stream(spliterator(), true);//返回的流是并行的 43 } 44 }
这里说明一下:
(1)JDK8版本中,接口中可以定义方法的实现了,即方法可以定义方法体了。
(2)Collection中定义了一些针对集合数据的添加,删除,判空,是否存在,整块集合的包含+移除等操作,以及JDK1.8开始新增的方法:removeIf()和spliterator(),stream()以及parallelStream()方法。
简单举个stream()的例子:
1 package com.xfwl.test; 2 3 import java.util.Arrays; 4 import java.util.List; 5 import java.util.function.Consumer; 6 import java.util.stream.Collectors; 7 @SuppressWarnings("unchecked") 8 public class Test2 { 9 public static void main(String[] args) { 10 List<Integer> alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10); 11 alist=alist.stream().filter(s -> (s>5)).collect(Collectors.toList());//lumbda表达式
12 for(int i:alist){ 13 System.out.println(i); 14 } 15 16 } 17 }
运行结果:
6
7
8
9
10
继续修改代码,举个removeIf()的例子:
1 package com.xfwl.test; 2 3 import java.util.Arrays; 4 import java.util.List; 5 import java.util.function.Consumer; 6 import java.util.stream.Collectors; 7 @SuppressWarnings("unchecked") 8 public class Test2 { 9 public static void main(String[] args) { 10 List<Integer> alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10); 11 alist=alist.stream().filter(s -> (s>5)).collect(Collectors.toList());//lumbda表达式 12 alist.removeIf(s->s==10); 13 for(int i:alist){ 14 System.out.println(i); 15 } 16 } 17 }
运行结果:
6
7
8
9
4、看看抽象类:AbstractCollection<E>中定义了那些规则?
JDK1.8中的源码
1 package java.util; 2 public abstract class AbstractCollection<E> implements Collection<E> { 3 protected AbstractCollection() { 4 } 5 public abstract Iterator<E> iterator(); 6 7 public abstract int size(); 8 9 public boolean isEmpty() { 10 return size() == 0; 11 } 12 public boolean contains(Object o) { 13 Iterator<E> it = iterator(); 14 if (o==null) { 15 while (it.hasNext()) 16 if (it.next()==null) 17 return true; 18 } else { 19 while (it.hasNext()) 20 if (o.equals(it.next())) 21 return true; 22 } 23 return false; 24 } 25 public Object[] toArray() { 26 // Estimate size of array; be prepared to see more or fewer elements 27 Object[] r = new Object[size()]; 28 Iterator<E> it = iterator(); 29 for (int i = 0; i < r.length; i++) { 30 if (! it.hasNext()) // fewer elements than expected 31 return Arrays.copyOf(r, i); 32 r[i] = it.next(); 33 } 34 return it.hasNext() ? finishToArray(r, it) : r; 35 } 36 @SuppressWarnings("unchecked") 37 public <T> T[] toArray(T[] a) { 38 // Estimate size of array; be prepared to see more or fewer elements 39 int size = size(); 40 T[] r = a.length >= size ? a : 41 (T[])java.lang.reflect.Array 42 .newInstance(a.getClass().getComponentType(), size); 43 Iterator<E> it = iterator(); 44 45 for (int i = 0; i < r.length; i++) { 46 if (! it.hasNext()) { // fewer elements than expected 47 if (a == r) { 48 r[i] = null; // null-terminate 49 } else if (a.length < i) { 50 return Arrays.copyOf(r, i); 51 } else { 52 System.arraycopy(r, 0, a, 0, i); 53 if (a.length > i) { 54 a[i] = null; 55 } 56 } 57 return a; 58 } 59 r[i] = (T)it.next(); 60 } 61 // more elements than expected 62 return it.hasNext() ? finishToArray(r, it) : r; 63 } 64 65 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 66 @SuppressWarnings("unchecked") 67 private static <T> T[] finishToArray(T[] r, Iterator<?> it) { 68 int i = r.length; 69 while (it.hasNext()) { 70 int cap = r.length; 71 if (i == cap) { 72 int newCap = cap + (cap >> 1) + 1; 73 // overflow-conscious code 74 if (newCap - MAX_ARRAY_SIZE > 0) 75 newCap = hugeCapacity(cap + 1); 76 r = Arrays.copyOf(r, newCap); 77 } 78 r[i++] = (T)it.next(); 79 } 80 // trim if overallocated 81 return (i == r.length) ? r : Arrays.copyOf(r, i); 82 } 83 84 private static int hugeCapacity(int minCapacity) { 85 if (minCapacity < 0) // overflow 86 throw new OutOfMemoryError 87 ("Required array size too large"); 88 return (minCapacity > MAX_ARRAY_SIZE) ? 89 Integer.MAX_VALUE : 90 MAX_ARRAY_SIZE; 91 } 92 public boolean add(E e) { 93 throw new UnsupportedOperationException(); 94 } 95 public boolean remove(Object o) { 96 Iterator<E> it = iterator(); 97 if (o==null) { 98 while (it.hasNext()) { 99 if (it.next()==null) { 100 it.remove(); 101 return true; 102 } 103 } 104 } else { 105 while (it.hasNext()) { 106 if (o.equals(it.next())) { 107 it.remove(); 108 return true; 109 } 110 } 111 } 112 return false; 113 } 114 public boolean containsAll(Collection<?> c) { 115 for (Object e : c) 116 if (!contains(e)) 117 return false; 118 return true; 119 } 120 public boolean addAll(Collection<? extends E> c) { 121 boolean modified = false; 122 for (E e : c) 123 if (add(e)) 124 modified = true; 125 return modified; 126 } 127 public boolean removeAll(Collection<?> c) { 128 Objects.requireNonNull(c); 129 boolean modified = false; 130 Iterator<?> it = iterator(); 131 while (it.hasNext()) { 132 if (c.contains(it.next())) { 133 it.remove(); 134 modified = true; 135 } 136 } 137 return modified; 138 } 139 public boolean retainAll(Collection<?> c) { 140 Objects.requireNonNull(c); 141 boolean modified = false; 142 Iterator<E> it = iterator(); 143 while (it.hasNext()) { 144 if (!c.contains(it.next())) { 145 it.remove(); 146 modified = true; 147 } 148 } 149 return modified; 150 } 151 public void clear() { 152 Iterator<E> it = iterator(); 153 while (it.hasNext()) { 154 it.next(); 155 it.remove(); 156 } 157 } 158 public String toString() { 159 Iterator<E> it = iterator(); 160 if (! it.hasNext()) 161 return "[]"; 162 163 StringBuilder sb = new StringBuilder(); 164 sb.append('['); 165 for (;;) { 166 E e = it.next(); 167 sb.append(e == this ? "(this Collection)" : e); 168 if (! it.hasNext()) 169 return sb.append(']').toString(); 170 sb.append(',').append(' '); 171 } 172 } 173 174 }
说明一下:
(1)整体上来看,抽象类:AbstractCollection<E>实现了Collection接口,并且定义了接口中没有实现的方法体。
(2)其中的: public abstract Iterator<E> iterator(); 依然是沿用之前jdk版本的使用方式,当前抽象类没有给出具体的实现,在另外一个抽象类AbstractList中给出了具体实现:
1 public Iterator<E> iterator() { 2 return new Itr(); 3 }
那么其中:new Itr()拿到的到底是什么呢?
继续贴出jdk中的源码:
1 private class Itr implements Iterator<E> { 2 int cursor = 0; //下一个元素的索引下标 3 int lastRet = -1; //上一个被调用的元素下标 4 int expectedModCount = modCount; 5 public boolean hasNext() { 6 return cursor != size(); 7 } 8 9 public E next() { //返回下一个元素 10 checkForComodification(); 11 try { 12 int i = cursor; 13 E next = get(i); 14 lastRet = i; 15 cursor = i + 1; 16 return next; 17 } catch (IndexOutOfBoundsException e) { 18 checkForComodification(); 19 throw new NoSuchElementException(); 20 } 21 } 22 23 public void remove() { //移除元素 24 if (lastRet < 0) 25 throw new IllegalStateException(); 26 checkForComodification(); 27 28 try { 29 AbstractList.this.remove(lastRet); 30 if (lastRet < cursor) 31 cursor--; 32 lastRet = -1; 33 expectedModCount = modCount; 34 } catch (IndexOutOfBoundsException e) { 35 throw new ConcurrentModificationException(); 36 } 37 } 38 39 final void checkForComodification() { 40 if (modCount != expectedModCount) 41 throw new ConcurrentModificationException(); 42 } 43 }
总结一下:
到目前为止,我们知道,如果只是想简单地获取集合的迭代器(非并行),可直接调用集合的iterator()方法即可,但是如果想要调用几何的并发的迭代器,则需要换一个JDK1.8新增进去的方法:
1 default Stream<E> stream() { //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据 2 return StreamSupport.stream(spliterator(), false);//返回的流是顺序的 3 } 4 default Stream<E> parallelStream() { //JDK1.8开始新加入的方法,通过传入并发迭代器,来使用stream过滤集合数据 5 return StreamSupport.stream(spliterator(), true);//返回的流是并行的 6 }
5、看看抽象类:AbstractList<E>中定义了那些规则?
贴上JDK1.8中的源码:
1 package java.util; 2 public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { 3 4 protected AbstractList() { 5 } 6 public boolean add(E e) { 7 add(size(), e); 8 return true; 9 } 10 11 abstract public E get(int index); 12 13 14 public E set(int index, E element) { 15 throw new UnsupportedOperationException(); 16 } 17 public void add(int index, E element) { 18 throw new UnsupportedOperationException(); 19 } 20 21 public E remove(int index) { 22 throw new UnsupportedOperationException(); 23 } 24 public int indexOf(Object o) { 25 ListIterator<E> it = listIterator(); 26 if (o==null) { 27 while (it.hasNext()) 28 if (it.next()==null) 29 return it.previousIndex(); 30 } else { 31 while (it.hasNext()) 32 if (o.equals(it.next())) 33 return it.previousIndex(); 34 } 35 return -1; 36 } 37 public int lastIndexOf(Object o) { 38 ListIterator<E> it = listIterator(size()); 39 if (o==null) { 40 while (it.hasPrevious()) 41 if (it.previous()==null) 42 return it.nextIndex(); 43 } else { 44 while (it.hasPrevious()) 45 if (o.equals(it.previous())) 46 return it.nextIndex(); 47 } 48 return -1; 49 } 50 51 public void clear() { 52 removeRange(0, size()); 53 } 54 public boolean addAll(int index, Collection<? extends E> c) { 55 rangeCheckForAdd(index); 56 boolean modified = false; 57 for (E e : c) { 58 add(index++, e); 59 modified = true; 60 } 61 return modified; 62 } 63 public Iterator<E> iterator() { 64 return new Itr(); 65 } 66 public ListIterator<E> listIterator() { 67 return listIterator(0); 68 } 69 public ListIterator<E> listIterator(final int index) { 70 rangeCheckForAdd(index); 71 72 return new ListItr(index); 73 } 74 75 private class Itr implements Iterator<E> { 76 77 int cursor = 0; 78 79 80 int lastRet = -1; 81 82 83 int expectedModCount = modCount; 84 85 public boolean hasNext() { 86 return cursor != size(); 87 } 88 89 public E next() { 90 checkForComodification(); 91 try { 92 int i = cursor; 93 E next = get(i); 94 lastRet = i; 95 cursor = i + 1; 96 return next; 97 } catch (IndexOutOfBoundsException e) { 98 checkForComodification(); 99 throw new NoSuchElementException(); 100 } 101 } 102 103 public void remove() { 104 if (lastRet < 0) 105 throw new IllegalStateException(); 106 checkForComodification(); 107 108 try { 109 AbstractList.this.remove(lastRet); 110 if (lastRet < cursor) 111 cursor--; 112 lastRet = -1; 113 expectedModCount = modCount; 114 } catch (IndexOutOfBoundsException e) { 115 throw new ConcurrentModificationException(); 116 } 117 } 118 119 final void checkForComodification() { 120 if (modCount != expectedModCount) 121 throw new ConcurrentModificationException(); 122 } 123 } 124 125 private class ListItr extends Itr implements ListIterator<E> { 126 ListItr(int index) { 127 cursor = index; 128 } 129 130 public boolean hasPrevious() { 131 return cursor != 0; 132 } 133 134 public E previous() { 135 checkForComodification(); 136 try { 137 int i = cursor - 1; 138 E previous = get(i); 139 lastRet = cursor = i; 140 return previous; 141 } catch (IndexOutOfBoundsException e) { 142 checkForComodification(); 143 throw new NoSuchElementException(); 144 } 145 } 146 147 public int nextIndex() { 148 return cursor; 149 } 150 151 public int previousIndex() { 152 return cursor-1; 153 } 154 155 public void set(E e) { 156 if (lastRet < 0) 157 throw new IllegalStateException(); 158 checkForComodification(); 159 160 try { 161 AbstractList.this.set(lastRet, e); 162 expectedModCount = modCount; 163 } catch (IndexOutOfBoundsException ex) { 164 throw new ConcurrentModificationException(); 165 } 166 } 167 168 public void add(E e) { 169 checkForComodification(); 170 171 try { 172 int i = cursor; 173 AbstractList.this.add(i, e); 174 lastRet = -1; 175 cursor = i + 1; 176 expectedModCount = modCount; 177 } catch (IndexOutOfBoundsException ex) { 178 throw new ConcurrentModificationException(); 179 } 180 } 181 } 182 public List<E> subList(int fromIndex, int toIndex) { 183 return (this instanceof RandomAccess ? 184 new RandomAccessSubList<>(this, fromIndex, toIndex) : 185 new SubList<>(this, fromIndex, toIndex)); 186 } 187 public boolean equals(Object o) { 188 if (o == this) 189 return true; 190 if (!(o instanceof List)) 191 return false; 192 193 ListIterator<E> e1 = listIterator(); 194 ListIterator<?> e2 = ((List<?>) o).listIterator(); 195 while (e1.hasNext() && e2.hasNext()) { 196 E o1 = e1.next(); 197 Object o2 = e2.next(); 198 if (!(o1==null ? o2==null : o1.equals(o2))) 199 return false; 200 } 201 return !(e1.hasNext() || e2.hasNext()); 202 } 203 public int hashCode() { 204 int hashCode = 1; 205 for (E e : this) 206 hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 207 return hashCode; 208 } 209 protected void removeRange(int fromIndex, int toIndex) { 210 ListIterator<E> it = listIterator(fromIndex); 211 for (int i=0, n=toIndex-fromIndex; i<n; i++) { 212 it.next(); 213 it.remove(); 214 } 215 } 216 protected transient int modCount = 0; 217 218 private void rangeCheckForAdd(int index) { 219 if (index < 0 || index > size()) 220 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 221 } 222 223 private String outOfBoundsMsg(int index) { 224 return "Index: "+index+", Size: "+size(); 225 } 226 } 227 228 class SubList<E> extends AbstractList<E> { 229 private final AbstractList<E> l; 230 private final int offset; 231 private int size; 232 233 SubList(AbstractList<E> list, int fromIndex, int toIndex) { 234 if (fromIndex < 0) 235 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); 236 if (toIndex > list.size()) 237 throw new IndexOutOfBoundsException("toIndex = " + toIndex); 238 if (fromIndex > toIndex) 239 throw new IllegalArgumentException("fromIndex(" + fromIndex + 240 ") > toIndex(" + toIndex + ")"); 241 l = list; 242 offset = fromIndex; 243 size = toIndex - fromIndex; 244 this.modCount = l.modCount; 245 } 246 247 public E set(int index, E element) { 248 rangeCheck(index); 249 checkForComodification(); 250 return l.set(index+offset, element); 251 } 252 253 public E get(int index) { 254 rangeCheck(index); 255 checkForComodification(); 256 return l.get(index+offset); 257 } 258 259 public int size() { 260 checkForComodification(); 261 return size; 262 } 263 264 public void add(int index, E element) { 265 rangeCheckForAdd(index); 266 checkForComodification(); 267 l.add(index+offset, element); 268 this.modCount = l.modCount; 269 size++; 270 } 271 272 public E remove(int index) { 273 rangeCheck(index); 274 checkForComodification(); 275 E result = l.remove(index+offset); 276 this.modCount = l.modCount; 277 size--; 278 return result; 279 } 280 281 protected void removeRange(int fromIndex, int toIndex) { 282 checkForComodification(); 283 l.removeRange(fromIndex+offset, toIndex+offset); 284 this.modCount = l.modCount; 285 size -= (toIndex-fromIndex); 286 } 287 288 public boolean addAll(Collection<? extends E> c) { 289 return addAll(size, c); 290 } 291 292 public boolean addAll(int index, Collection<? extends E> c) { 293 rangeCheckForAdd(index); 294 int cSize = c.size(); 295 if (cSize==0) 296 return false; 297 298 checkForComodification(); 299 l.addAll(offset+index, c); 300 this.modCount = l.modCount; 301 size += cSize; 302 return true; 303 } 304 305 public Iterator<E> iterator() { 306 return listIterator(); 307 } 308 309 public ListIterator<E> listIterator(final int index) { 310 checkForComodification(); 311 rangeCheckForAdd(index); 312 313 return new ListIterator<E>() { 314 private final ListIterator<E> i = l.listIterator(index+offset); 315 316 public boolean hasNext() { 317 return nextIndex() < size; 318 } 319 320 public E next() { 321 if (hasNext()) 322 return i.next(); 323 else 324 throw new NoSuchElementException(); 325 } 326 327 public boolean hasPrevious() { 328 return previousIndex() >= 0; 329 } 330 331 public E previous() { 332 if (hasPrevious()) 333 return i.previous(); 334 else 335 throw new NoSuchElementException(); 336 } 337 338 public int nextIndex() { 339 return i.nextIndex() - offset; 340 } 341 342 public int previousIndex() { 343 return i.previousIndex() - offset; 344 } 345 346 public void remove() { 347 i.remove(); 348 SubList.this.modCount = l.modCount; 349 size--; 350 } 351 352 public void set(E e) { 353 i.set(e); 354 } 355 356 public void add(E e) { 357 i.add(e); 358 SubList.this.modCount = l.modCount; 359 size++; 360 } 361 }; 362 } 363 364 public List<E> subList(int fromIndex, int toIndex) { 365 return new SubList<>(this, fromIndex, toIndex); 366 } 367 368 private void rangeCheck(int index) { 369 if (index < 0 || index >= size) 370 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 371 } 372 373 private void rangeCheckForAdd(int index) { 374 if (index < 0 || index > size) 375 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 376 } 377 378 private String outOfBoundsMsg(int index) { 379 return "Index: "+index+", Size: "+size; 380 } 381 382 private void checkForComodification() { 383 if (this.modCount != l.modCount) 384 throw new ConcurrentModificationException(); 385 } 386 } 387 388 class RandomAccessSubList<E> extends SubList<E> implements RandomAccess { 389 RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) { 390 super(list, fromIndex, toIndex); 391 } 392 393 public List<E> subList(int fromIndex, int toIndex) { 394 return new RandomAccessSubList<>(this, fromIndex, toIndex); 395 } 396 }
简单看一下抽象类的结构图:
说明一下:
这个抽象类中存在:抽象方法的声明,一些具体方法的实现,也内置了一些内部类:
private class Itr implements Iterator<E> {}
private class ListItr extends Itr implements ListIterator<E> {}
以上2两种迭代器丰富了AbstractList这个抽象类的迭代方式,以后继承这个抽象类的子类也可以重写会直接复用,为子类提供了多样化的功能。
一直在说:以上的接口或者抽象类只是在定义集合的规则,有些人就会有疑惑了,明明这个接口或者抽象类中也有一些实现了功能的方法啊。
其实对于一个集合来说,最重要的是什么?是如何把数据存进去,存在哪里,如何存放,如何取出来,如何存放到一个迭代器中(我们都知道是以链表的形式存放),那么从上面的接口或者抽象类中,我并没有发现:
(1)数据的存放的位置(数组,list集合中维护的是数组)。
(2)数据如何存放在迭代器中的链表。
以上这2中核心实现的代码,并不存在于上述的接口和抽象类中,所以我们接着往下看,继续去寻找答案!!!
6、看看接口:List<E>中定义了那些规则?
贴上JDK1.8中的源码:
1 package java.util; 2 import java.util.function.UnaryOperator; 3 public interface List<E> extends Collection<E> { 4 // Query Operations 5 6 /** 7 * Returns the number of elements in this list. If this list contains 8 * more than <tt>Integer.MAX_VALUE</tt> elements, returns 9 * <tt>Integer.MAX_VALUE</tt>. 10 * 11 * @return the number of elements in this list 12 */ 13 int size(); 14 15 /** 16 * Returns <tt>true</tt> if this list contains no elements. 17 * 18 * @return <tt>true</tt> if this list contains no elements 19 */ 20 boolean isEmpty(); 21 22 /** 23 * Returns <tt>true</tt> if this list contains the specified element. 24 * More formally, returns <tt>true</tt> if and only if this list contains 25 * at least one element <tt>e</tt> such that 26 * <tt>(o==null ? e==null : o.equals(e))</tt>. 27 * 28 * @param o element whose presence in this list is to be tested 29 * @return <tt>true</tt> if this list contains the specified element 30 * @throws ClassCastException if the type of the specified element 31 * is incompatible with this list 32 * (<a href="Collection.html#optional-restrictions">optional</a>) 33 * @throws NullPointerException if the specified element is null and this 34 * list does not permit null elements 35 * (<a href="Collection.html#optional-restrictions">optional</a>) 36 */ 37 boolean contains(Object o); 38 39 /** 40 * Returns an iterator over the elements in this list in proper sequence. 41 * 42 * @return an iterator over the elements in this list in proper sequence 43 */ 44 Iterator<E> iterator(); 45 46 /** 47 * Returns an array containing all of the elements in this list in proper 48 * sequence (from first to last element). 49 * 50 * <p>The returned array will be "safe" in that no references to it are 51 * maintained by this list. (In other words, this method must 52 * allocate a new array even if this list is backed by an array). 53 * The caller is thus free to modify the returned array. 54 * 55 * <p>This method acts as bridge between array-based and collection-based 56 * APIs. 57 * 58 * @return an array containing all of the elements in this list in proper 59 * sequence 60 * @see Arrays#asList(Object[]) 61 */ 62 Object[] toArray(); 63 64 /** 65 * Returns an array containing all of the elements in this list in 66 * proper sequence (from first to last element); the runtime type of 67 * the returned array is that of the specified array. If the list fits 68 * in the specified array, it is returned therein. Otherwise, a new 69 * array is allocated with the runtime type of the specified array and 70 * the size of this list. 71 * 72 * <p>If the list fits in the specified array with room to spare (i.e., 73 * the array has more elements than the list), the element in the array 74 * immediately following the end of the list is set to <tt>null</tt>. 75 * (This is useful in determining the length of the list <i>only</i> if 76 * the caller knows that the list does not contain any null elements.) 77 * 78 * <p>Like the {@link #toArray()} method, this method acts as bridge between 79 * array-based and collection-based APIs. Further, this method allows 80 * precise control over the runtime type of the output array, and may, 81 * under certain circumstances, be used to save allocation costs. 82 * 83 * <p>Suppose <tt>x</tt> is a list known to contain only strings. 84 * The following code can be used to dump the list into a newly 85 * allocated array of <tt>String</tt>: 86 * 87 * <pre>{@code 88 * String[] y = x.toArray(new String[0]); 89 * }</pre> 90 * 91 * Note that <tt>toArray(new Object[0])</tt> is identical in function to 92 * <tt>toArray()</tt>. 93 * 94 * @param a the array into which the elements of this list are to 95 * be stored, if it is big enough; otherwise, a new array of the 96 * same runtime type is allocated for this purpose. 97 * @return an array containing the elements of this list 98 * @throws ArrayStoreException if the runtime type of the specified array 99 * is not a supertype of the runtime type of every element in 100 * this list 101 * @throws NullPointerException if the specified array is null 102 */ 103 <T> T[] toArray(T[] a); 104 105 106 // Modification Operations 107 108 /** 109 * Appends the specified element to the end of this list (optional 110 * operation). 111 * 112 * <p>Lists that support this operation may place limitations on what 113 * elements may be added to this list. In particular, some 114 * lists will refuse to add null elements, and others will impose 115 * restrictions on the type of elements that may be added. List 116 * classes should clearly specify in their documentation any restrictions 117 * on what elements may be added. 118 * 119 * @param e element to be appended to this list 120 * @return <tt>true</tt> (as specified by {@link Collection#add}) 121 * @throws UnsupportedOperationException if the <tt>add</tt> operation 122 * is not supported by this list 123 * @throws ClassCastException if the class of the specified element 124 * prevents it from being added to this list 125 * @throws NullPointerException if the specified element is null and this 126 * list does not permit null elements 127 * @throws IllegalArgumentException if some property of this element 128 * prevents it from being added to this list 129 */ 130 boolean add(E e); 131 132 /** 133 * Removes the first occurrence of the specified element from this list, 134 * if it is present (optional operation). If this list does not contain 135 * the element, it is unchanged. More formally, removes the element with 136 * the lowest index <tt>i</tt> such that 137 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> 138 * (if such an element exists). Returns <tt>true</tt> if this list 139 * contained the specified element (or equivalently, if this list changed 140 * as a result of the call). 141 * 142 * @param o element to be removed from this list, if present 143 * @return <tt>true</tt> if this list contained the specified element 144 * @throws ClassCastException if the type of the specified element 145 * is incompatible with this list 146 * (<a href="Collection.html#optional-restrictions">optional</a>) 147 * @throws NullPointerException if the specified element is null and this 148 * list does not permit null elements 149 * (<a href="Collection.html#optional-restrictions">optional</a>) 150 * @throws UnsupportedOperationException if the <tt>remove</tt> operation 151 * is not supported by this list 152 */ 153 boolean remove(Object o); 154 155 156 // Bulk Modification Operations 157 158 /** 159 * Returns <tt>true</tt> if this list contains all of the elements of the 160 * specified collection. 161 * 162 * @param c collection to be checked for containment in this list 163 * @return <tt>true</tt> if this list contains all of the elements of the 164 * specified collection 165 * @throws ClassCastException if the types of one or more elements 166 * in the specified collection are incompatible with this 167 * list 168 * (<a href="Collection.html#optional-restrictions">optional</a>) 169 * @throws NullPointerException if the specified collection contains one 170 * or more null elements and this list does not permit null 171 * elements 172 * (<a href="Collection.html#optional-restrictions">optional</a>), 173 * or if the specified collection is null 174 * @see #contains(Object) 175 */ 176 boolean containsAll(Collection<?> c); 177 178 /** 179 * Appends all of the elements in the specified collection to the end of 180 * this list, in the order that they are returned by the specified 181 * collection's iterator (optional operation). The behavior of this 182 * operation is undefined if the specified collection is modified while 183 * the operation is in progress. (Note that this will occur if the 184 * specified collection is this list, and it's nonempty.) 185 * 186 * @param c collection containing elements to be added to this list 187 * @return <tt>true</tt> if this list changed as a result of the call 188 * @throws UnsupportedOperationException if the <tt>addAll</tt> operation 189 * is not supported by this list 190 * @throws ClassCastException if the class of an element of the specified 191 * collection prevents it from being added to this list 192 * @throws NullPointerException if the specified collection contains one 193 * or more null elements and this list does not permit null 194 * elements, or if the specified collection is null 195 * @throws IllegalArgumentException if some property of an element of the 196 * specified collection prevents it from being added to this list 197 * @see #add(Object) 198 */ 199 boolean addAll(Collection<? extends E> c); 200 201 /** 202 * Inserts all of the elements in the specified collection into this 203 * list at the specified position (optional operation). Shifts the 204 * element currently at that position (if any) and any subsequent 205 * elements to the right (increases their indices). The new elements 206 * will appear in this list in the order that they are returned by the 207 * specified collection's iterator. The behavior of this operation is 208 * undefined if the specified collection is modified while the 209 * operation is in progress. (Note that this will occur if the specified 210 * collection is this list, and it's nonempty.) 211 * 212 * @param index index at which to insert the first element from the 213 * specified collection 214 * @param c collection containing elements to be added to this list 215 * @return <tt>true</tt> if this list changed as a result of the call 216 * @throws UnsupportedOperationException if the <tt>addAll</tt> operation 217 * is not supported by this list 218 * @throws ClassCastException if the class of an element of the specified 219 * collection prevents it from being added to this list 220 * @throws NullPointerException if the specified collection contains one 221 * or more null elements and this list does not permit null 222 * elements, or if the specified collection is null 223 * @throws IllegalArgumentException if some property of an element of the 224 * specified collection prevents it from being added to this list 225 * @throws IndexOutOfBoundsException if the index is out of range 226 * (<tt>index < 0 || index > size()</tt>) 227 */ 228 boolean addAll(int index, Collection<? extends E> c); 229 230 /** 231 * Removes from this list all of its elements that are contained in the 232 * specified collection (optional operation). 233 * 234 * @param c collection containing elements to be removed from this list 235 * @return <tt>true</tt> if this list changed as a result of the call 236 * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation 237 * is not supported by this list 238 * @throws ClassCastException if the class of an element of this list 239 * is incompatible with the specified collection 240 * (<a href="Collection.html#optional-restrictions">optional</a>) 241 * @throws NullPointerException if this list contains a null element and the 242 * specified collection does not permit null elements 243 * (<a href="Collection.html#optional-restrictions">optional</a>), 244 * or if the specified collection is null 245 * @see #remove(Object) 246 * @see #contains(Object) 247 */ 248 boolean removeAll(Collection<?> c); 249 250 /** 251 * Retains only the elements in this list that are contained in the 252 * specified collection (optional operation). In other words, removes 253 * from this list all of its elements that are not contained in the 254 * specified collection. 255 * 256 * @param c collection containing elements to be retained in this list 257 * @return <tt>true</tt> if this list changed as a result of the call 258 * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation 259 * is not supported by this list 260 * @throws ClassCastException if the class of an element of this list 261 * is incompatible with the specified collection 262 * (<a href="Collection.html#optional-restrictions">optional</a>) 263 * @throws NullPointerException if this list contains a null element and the 264 * specified collection does not permit null elements 265 * (<a href="Collection.html#optional-restrictions">optional</a>), 266 * or if the specified collection is null 267 * @see #remove(Object) 268 * @see #contains(Object) 269 */ 270 boolean retainAll(Collection<?> c); 271 272 /** 273 * Replaces each element of this list with the result of applying the 274 * operator to that element. Errors or runtime exceptions thrown by 275 * the operator are relayed to the caller. 276 * 277 * @implSpec 278 * The default implementation is equivalent to, for this {@code list}: 279 * <pre>{@code 280 * final ListIterator<E> li = list.listIterator(); 281 * while (li.hasNext()) { 282 * li.set(operator.apply(li.next())); 283 * } 284 * }</pre> 285 * 286 * If the list's list-iterator does not support the {@code set} operation 287 * then an {@code UnsupportedOperationException} will be thrown when 288 * replacing the first element. 289 * 290 * @param operator the operator to apply to each element 291 * @throws UnsupportedOperationException if this list is unmodifiable. 292 * Implementations may throw this exception if an element 293 * cannot be replaced or if, in general, modification is not 294 * supported 295 * @throws NullPointerException if the specified operator is null or 296 * if the operator result is a null value and this list does 297 * not permit null elements 298 * (<a href="Collection.html#optional-restrictions">optional</a>) 299 * @since 1.8 300 */ 301 default void replaceAll(UnaryOperator<E> operator) { 302 Objects.requireNonNull(operator); 303 final ListIterator<E> li = this.listIterator(); 304 while (li.hasNext()) { 305 li.set(operator.apply(li.next())); 306 } 307 } 308 309 /** 310 * Sorts this list according to the order induced by the specified 311 * {@link Comparator}. 312 * 313 * <p>All elements in this list must be <i>mutually comparable</i> using the 314 * specified comparator (that is, {@code c.compare(e1, e2)} must not throw 315 * a {@code ClassCastException} for any elements {@code e1} and {@code e2} 316 * in the list). 317 * 318 * <p>If the specified comparator is {@code null} then all elements in this 319 * list must implement the {@link Comparable} interface and the elements' 320 * {@linkplain Comparable natural ordering} should be used. 321 * 322 * <p>This list must be modifiable, but need not be resizable. 323 * 324 * @implSpec 325 * The default implementation obtains an array containing all elements in 326 * this list, sorts the array, and iterates over this list resetting each 327 * element from the corresponding position in the array. (This avoids the 328 * n<sup>2</sup> log(n) performance that would result from attempting 329 * to sort a linked list in place.) 330 * 331 * @implNote 332 * This implementation is a stable, adaptive, iterative mergesort that 333 * requires far fewer than n lg(n) comparisons when the input array is 334 * partially sorted, while offering the performance of a traditional 335 * mergesort when the input array is randomly ordered. If the input array 336 * is nearly sorted, the implementation requires approximately n 337 * comparisons. Temporary storage requirements vary from a small constant 338 * for nearly sorted input arrays to n/2 object references for randomly 339 * ordered input arrays. 340 * 341 * <p>The implementation takes equal advantage of ascending and 342 * descending order in its input array, and can take advantage of 343 * ascending and descending order in different parts of the same 344 * input array. It is well-suited to merging two or more sorted arrays: 345 * simply concatenate the arrays and sort the resulting array. 346 * 347 * <p>The implementation was adapted from Tim Peters's list sort for Python 348 * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt"> 349 * TimSort</a>). It uses techniques from Peter McIlroy's "Optimistic 350 * Sorting and Information Theoretic Complexity", in Proceedings of the 351 * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, 352 * January 1993. 353 * 354 * @param c the {@code Comparator} used to compare list elements. 355 * A {@code null} value indicates that the elements' 356 * {@linkplain Comparable natural ordering} should be used 357 * @throws ClassCastException if the list contains elements that are not 358 * <i>mutually comparable</i> using the specified comparator 359 * @throws UnsupportedOperationException if the list's list-iterator does 360 * not support the {@code set} operation 361 * @throws IllegalArgumentException 362 * (<a href="Collection.html#optional-restrictions">optional</a>) 363 * if the comparator is found to violate the {@link Comparator} 364 * contract 365 * @since 1.8 366 */ 367 @SuppressWarnings({"unchecked", "rawtypes"}) 368 default void sort(Comparator<? super E> c) { 369 Object[] a = this.toArray(); 370 Arrays.sort(a, (Comparator) c); 371 ListIterator<E> i = this.listIterator(); 372 for (Object e : a) { 373 i.next(); 374 i.set((E) e); 375 } 376 } 377 378 /** 379 * Removes all of the elements from this list (optional operation). 380 * The list will be empty after this call returns. 381 * 382 * @throws UnsupportedOperationException if the <tt>clear</tt> operation 383 * is not supported by this list 384 */ 385 void clear(); 386 387 388 // Comparison and hashing 389 390 /** 391 * Compares the specified object with this list for equality. Returns 392 * <tt>true</tt> if and only if the specified object is also a list, both 393 * lists have the same size, and all corresponding pairs of elements in 394 * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and 395 * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null : 396 * e1.equals(e2))</tt>.) In other words, two lists are defined to be 397 * equal if they contain the same elements in the same order. This 398 * definition ensures that the equals method works properly across 399 * different implementations of the <tt>List</tt> interface. 400 * 401 * @param o the object to be compared for equality with this list 402 * @return <tt>true</tt> if the specified object is equal to this list 403 */ 404 boolean equals(Object o); 405 406 /** 407 * Returns the hash code value for this list. The hash code of a list 408 * is defined to be the result of the following calculation: 409 * <pre>{@code 410 * int hashCode = 1; 411 * for (E e : list) 412 * hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 413 * }</pre> 414 * This ensures that <tt>list1.equals(list2)</tt> implies that 415 * <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists, 416 * <tt>list1</tt> and <tt>list2</tt>, as required by the general 417 * contract of {@link Object#hashCode}. 418 * 419 * @return the hash code value for this list 420 * @see Object#equals(Object) 421 * @see #equals(Object) 422 */ 423 int hashCode(); 424 425 426 // Positional Access Operations 427 428 /** 429 * Returns the element at the specified position in this list. 430 * 431 * @param index index of the element to return 432 * @return the element at the specified position in this list 433 * @throws IndexOutOfBoundsException if the index is out of range 434 * (<tt>index < 0 || index >= size()</tt>) 435 */ 436 E get(int index); 437 438 /** 439 * Replaces the element at the specified position in this list with the 440 * specified element (optional operation). 441 * 442 * @param index index of the element to replace 443 * @param element element to be stored at the specified position 444 * @return the element previously at the specified position 445 * @throws UnsupportedOperationException if the <tt>set</tt> operation 446 * is not supported by this list 447 * @throws ClassCastException if the class of the specified element 448 * prevents it from being added to this list 449 * @throws NullPointerException if the specified element is null and 450 * this list does not permit null elements 451 * @throws IllegalArgumentException if some property of the specified 452 * element prevents it from being added to this list 453 * @throws IndexOutOfBoundsException if the index is out of range 454 * (<tt>index < 0 || index >= size()</tt>) 455 */ 456 E set(int index, E element); 457 458 /** 459 * Inserts the specified element at the specified position in this list 460 * (optional operation). Shifts the element currently at that position 461 * (if any) and any subsequent elements to the right (adds one to their 462 * indices). 463 * 464 * @param index index at which the specified element is to be inserted 465 * @param element element to be inserted 466 * @throws UnsupportedOperationException if the <tt>add</tt> operation 467 * is not supported by this list 468 * @throws ClassCastException if the class of the specified element 469 * prevents it from being added to this list 470 * @throws NullPointerException if the specified element is null and 471 * this list does not permit null elements 472 * @throws IllegalArgumentException if some property of the specified 473 * element prevents it from being added to this list 474 * @throws IndexOutOfBoundsException if the index is out of range 475 * (<tt>index < 0 || index > size()</tt>) 476 */ 477 void add(int index, E element); 478 479 /** 480 * Removes the element at the specified position in this list (optional 481 * operation). Shifts any subsequent elements to the left (subtracts one 482 * from their indices). Returns the element that was removed from the 483 * list. 484 * 485 * @param index the index of the element to be removed 486 * @return the element previously at the specified position 487 * @throws UnsupportedOperationException if the <tt>remove</tt> operation 488 * is not supported by this list 489 * @throws IndexOutOfBoundsException if the index is out of range 490 * (<tt>index < 0 || index >= size()</tt>) 491 */ 492 E remove(int index); 493 494 495 // Search Operations 496 497 /** 498 * Returns the index of the first occurrence of the specified element 499 * in this list, or -1 if this list does not contain the element. 500 * More formally, returns the lowest index <tt>i</tt> such that 501 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 502 * or -1 if there is no such index. 503 * 504 * @param o element to search for 505 * @return the index of the first occurrence of the specified element in 506 * this list, or -1 if this list does not contain the element 507 * @throws ClassCastException if the type of the specified element 508 * is incompatible with this list 509 * (<a href="Collection.html#optional-restrictions">optional</a>) 510 * @throws NullPointerException if the specified element is null and this 511 * list does not permit null elements 512 * (<a href="Collection.html#optional-restrictions">optional</a>) 513 */ 514 int indexOf(Object o); 515 516 /** 517 * Returns the index of the last occurrence of the specified element 518 * in this list, or -1 if this list does not contain the element. 519 * More formally, returns the highest index <tt>i</tt> such that 520 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 521 * or -1 if there is no such index. 522 * 523 * @param o element to search for 524 * @return the index of the last occurrence of the specified element in 525 * this list, or -1 if this list does not contain the element 526 * @throws ClassCastException if the type of the specified element 527 * is incompatible with this list 528 * (<a href="Collection.html#optional-restrictions">optional</a>) 529 * @throws NullPointerException if the specified element is null and this 530 * list does not permit null elements 531 * (<a href="Collection.html#optional-restrictions">optional</a>) 532 */ 533 int lastIndexOf(Object o); 534 535 536 // List Iterators 537 538 /** 539 * Returns a list iterator over the elements in this list (in proper 540 * sequence). 541 * 542 * @return a list iterator over the elements in this list (in proper 543 * sequence) 544 */ 545 ListIterator<E> listIterator(); 546 547 /** 548 * Returns a list iterator over the elements in this list (in proper 549 * sequence), starting at the specified position in the list. 550 * The specified index indicates the first element that would be 551 * returned by an initial call to {@link ListIterator#next next}. 552 * An initial call to {@link ListIterator#previous previous} would 553 * return the element with the specified index minus one. 554 * 555 * @param index index of the first element to be returned from the 556 * list iterator (by a call to {@link ListIterator#next next}) 557 * @return a list iterator over the elements in this list (in proper 558 * sequence), starting at the specified position in the list 559 * @throws IndexOutOfBoundsException if the index is out of range 560 * ({@code index < 0 || index > size()}) 561 */ 562 ListIterator<E> listIterator(int index); 563 564 // View 565 566 /** 567 * Returns a view of the portion of this list between the specified 568 * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive. (If 569 * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is 570 * empty.) The returned list is backed by this list, so non-structural 571 * changes in the returned list are reflected in this list, and vice-versa. 572 * The returned list supports all of the optional list operations supported 573 * by this list.<p> 574 * 575 * This method eliminates the need for explicit range operations (of 576 * the sort that commonly exist for arrays). Any operation that expects 577 * a list can be used as a range operation by passing a subList view 578 * instead of a whole list. For example, the following idiom 579 * removes a range of elements from a list: 580 * <pre>{@code 581 * list.subList(from, to).clear(); 582 * }</pre> 583 * Similar idioms may be constructed for <tt>indexOf</tt> and 584 * <tt>lastIndexOf</tt>, and all of the algorithms in the 585 * <tt>Collections</tt> class can be applied to a subList.<p> 586 * 587 * The semantics of the list returned by this method become undefined if 588 * the backing list (i.e., this list) is <i>structurally modified</i> in 589 * any way other than via the returned list. (Structural modifications are 590 * those that change the size of this list, or otherwise perturb it in such 591 * a fashion that iterations in progress may yield incorrect results.) 592 * 593 * @param fromIndex low endpoint (inclusive) of the subList 594 * @param toIndex high endpoint (exclusive) of the subList 595 * @return a view of the specified range within this list 596 * @throws IndexOutOfBoundsException for an illegal endpoint index value 597 * (<tt>fromIndex < 0 || toIndex > size || 598 * fromIndex > toIndex</tt>) 599 */ 600 List<E> subList(int fromIndex, int toIndex); 601 602 /** 603 * Creates a {@link Spliterator} over the elements in this list. 604 * 605 * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and 606 * {@link Spliterator#ORDERED}. Implementations should document the 607 * reporting of additional characteristic values. 608 * 609 * @implSpec 610 * The default implementation creates a 611 * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator 612 * from the list's {@code Iterator}. The spliterator inherits the 613 * <em>fail-fast</em> properties of the list's iterator. 614 * 615 * @implNote 616 * The created {@code Spliterator} additionally reports 617 * {@link Spliterator#SUBSIZED}. 618 * 619 * @return a {@code Spliterator} over the elements in this list 620 * @since 1.8 621 */ 622 @Override 623 default Spliterator<E> spliterator() { 624 return Spliterators.spliterator(this, Spliterator.ORDERED); 625 } 626 }
简单看一下抽象类的结构图:
说明一下:
从源码和抽象类的结构图中,同样可以看到:
(1)List接口中没有说明集合数据是存放在哪里的?只是声明了一些集合操作的方法。、
(2)List接口中没有看到迭代器是如何获取集合数据并存放到链表中的:如下:
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
所以想要探明究竟,就只能继续往下看,层层往下,直到ArrayList实现子类。
7、看看实现类:ArrayList<E>是如何实现集合功能的?
贴上JDK1.8中的源码:(内容有点多,会在下面捡重要的说明一下)
1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12 * 13 * 14 * 15 * 16 * 17 * 18 * 19 * 20 * 21 * 22 * 23 * 24 */ 25 26 package java.util; 27 28 import java.util.function.Consumer; 29 import java.util.function.Predicate; 30 import java.util.function.UnaryOperator; 31 32 /** 33 * Resizable-array implementation of the <tt>List</tt> interface. Implements 34 * all optional list operations, and permits all elements, including 35 * <tt>null</tt>. In addition to implementing the <tt>List</tt> interface, 36 * this class provides methods to manipulate the size of the array that is 37 * used internally to store the list. (This class is roughly equivalent to 38 * <tt>Vector</tt>, except that it is unsynchronized.) 39 * 40 * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>, 41 * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant 42 * time. The <tt>add</tt> operation runs in <i>amortized constant time</i>, 43 * that is, adding n elements requires O(n) time. All of the other operations 44 * run in linear time (roughly speaking). The constant factor is low compared 45 * to that for the <tt>LinkedList</tt> implementation. 46 * 47 * <p>Each <tt>ArrayList</tt> instance has a <i>capacity</i>. The capacity is 48 * the size of the array used to store the elements in the list. It is always 49 * at least as large as the list size. As elements are added to an ArrayList, 50 * its capacity grows automatically. The details of the growth policy are not 51 * specified beyond the fact that adding an element has constant amortized 52 * time cost. 53 * 54 * <p>An application can increase the capacity of an <tt>ArrayList</tt> instance 55 * before adding a large number of elements using the <tt>ensureCapacity</tt> 56 * operation. This may reduce the amount of incremental reallocation. 57 * 58 * <p><strong>Note that this implementation is not synchronized.</strong> 59 * If multiple threads access an <tt>ArrayList</tt> instance concurrently, 60 * and at least one of the threads modifies the list structurally, it 61 * <i>must</i> be synchronized externally. (A structural modification is 62 * any operation that adds or deletes one or more elements, or explicitly 63 * resizes the backing array; merely setting the value of an element is not 64 * a structural modification.) This is typically accomplished by 65 * synchronizing on some object that naturally encapsulates the list. 66 * 67 * If no such object exists, the list should be "wrapped" using the 68 * {@link Collections#synchronizedList Collections.synchronizedList} 69 * method. This is best done at creation time, to prevent accidental 70 * unsynchronized access to the list:<pre> 71 * List list = Collections.synchronizedList(new ArrayList(...));</pre> 72 * 73 * <p><a name="fail-fast"> 74 * The iterators returned by this class's {@link #iterator() iterator} and 75 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:</a> 76 * if the list is structurally modified at any time after the iterator is 77 * created, in any way except through the iterator's own 78 * {@link ListIterator#remove() remove} or 79 * {@link ListIterator#add(Object) add} methods, the iterator will throw a 80 * {@link ConcurrentModificationException}. Thus, in the face of 81 * concurrent modification, the iterator fails quickly and cleanly, rather 82 * than risking arbitrary, non-deterministic behavior at an undetermined 83 * time in the future. 84 * 85 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 86 * as it is, generally speaking, impossible to make any hard guarantees in the 87 * presence of unsynchronized concurrent modification. Fail-fast iterators 88 * throw {@code ConcurrentModificationException} on a best-effort basis. 89 * Therefore, it would be wrong to write a program that depended on this 90 * exception for its correctness: <i>the fail-fast behavior of iterators 91 * should be used only to detect bugs.</i> 92 * 93 * <p>This class is a member of the 94 * <a href="{@docRoot}/../technotes/guides/collections/index.html"> 95 * Java Collections Framework</a>. 96 * 97 * @author Josh Bloch 98 * @author Neal Gafter 99 * @see Collection 100 * @see List 101 * @see LinkedList 102 * @see Vector 103 * @since 1.2 104 */ 105 106 public class ArrayList<E> extends AbstractList<E> 107 implements List<E>, RandomAccess, Cloneable, java.io.Serializable 108 { 109 private static final long serialVersionUID = 8683452581122892189L; 110 111 /** 112 * Default initial capacity. 113 */ 114 private static final int DEFAULT_CAPACITY = 10; 115 116 /** 117 * Shared empty array instance used for empty instances. 118 */ 119 private static final Object[] EMPTY_ELEMENTDATA = {}; 120 121 /** 122 * Shared empty array instance used for default sized empty instances. We 123 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when 124 * first element is added. 125 */ 126 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 127 128 /** 129 * The array buffer into which the elements of the ArrayList are stored. 130 * The capacity of the ArrayList is the length of this array buffer. Any 131 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 132 * will be expanded to DEFAULT_CAPACITY when the first element is added. 133 */ 134 transient Object[] elementData; // non-private to simplify nested class access 135 136 /** 137 * The size of the ArrayList (the number of elements it contains). 138 * 139 * @serial 140 */ 141 private int size; 142 143 /** 144 * Constructs an empty list with the specified initial capacity. 145 * 146 * @param initialCapacity the initial capacity of the list 147 * @throws IllegalArgumentException if the specified initial capacity 148 * is negative 149 */ 150 public ArrayList(int initialCapacity) { 151 if (initialCapacity > 0) { 152 this.elementData = new Object[initialCapacity]; 153 } else if (initialCapacity == 0) { 154 this.elementData = EMPTY_ELEMENTDATA; 155 } else { 156 throw new IllegalArgumentException("Illegal Capacity: "+ 157 initialCapacity); 158 } 159 } 160 161 /** 162 * Constructs an empty list with an initial capacity of ten. 163 */ 164 public ArrayList() { 165 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 166 } 167 168 /** 169 * Constructs a list containing the elements of the specified 170 * collection, in the order they are returned by the collection's 171 * iterator. 172 * 173 * @param c the collection whose elements are to be placed into this list 174 * @throws NullPointerException if the specified collection is null 175 */ 176 public ArrayList(Collection<? extends E> c) { 177 elementData = c.toArray(); 178 if ((size = elementData.length) != 0) { 179 // c.toArray might (incorrectly) not return Object[] (see 6260652) 180 if (elementData.getClass() != Object[].class) 181 elementData = Arrays.copyOf(elementData, size, Object[].class); 182 } else { 183 // replace with empty array. 184 this.elementData = EMPTY_ELEMENTDATA; 185 } 186 } 187 188 /** 189 * Trims the capacity of this <tt>ArrayList</tt> instance to be the 190 * list's current size. An application can use this operation to minimize 191 * the storage of an <tt>ArrayList</tt> instance. 192 */ 193 public void trimToSize() { 194 modCount++; 195 if (size < elementData.length) { 196 elementData = (size == 0) 197 ? EMPTY_ELEMENTDATA 198 : Arrays.copyOf(elementData, size); 199 } 200 } 201 202 /** 203 * Increases the capacity of this <tt>ArrayList</tt> instance, if 204 * necessary, to ensure that it can hold at least the number of elements 205 * specified by the minimum capacity argument. 206 * 207 * @param minCapacity the desired minimum capacity 208 */ 209 public void ensureCapacity(int minCapacity) { 210 int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 211 // any size if not default element table 212 ? 0 213 // larger than default for default empty table. It's already 214 // supposed to be at default size. 215 : DEFAULT_CAPACITY; 216 217 if (minCapacity > minExpand) { 218 ensureExplicitCapacity(minCapacity); 219 } 220 } 221 222 private void ensureCapacityInternal(int minCapacity) { 223 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 224 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 225 } 226 227 ensureExplicitCapacity(minCapacity); 228 } 229 230 private void ensureExplicitCapacity(int minCapacity) { 231 modCount++; 232 233 // overflow-conscious code 234 if (minCapacity - elementData.length > 0) 235 grow(minCapacity); 236 } 237 238 /** 239 * The maximum size of array to allocate. 240 * Some VMs reserve some header words in an array. 241 * Attempts to allocate larger arrays may result in 242 * OutOfMemoryError: Requested array size exceeds VM limit 243 */ 244 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 245 246 /** 247 * Increases the capacity to ensure that it can hold at least the 248 * number of elements specified by the minimum capacity argument. 249 * 250 * @param minCapacity the desired minimum capacity 251 */ 252 private void grow(int minCapacity) { 253 // overflow-conscious code 254 int oldCapacity = elementData.length; 255 int newCapacity = oldCapacity + (oldCapacity >> 1); 256 if (newCapacity - minCapacity < 0) 257 newCapacity = minCapacity; 258 if (newCapacity - MAX_ARRAY_SIZE > 0) 259 newCapacity = hugeCapacity(minCapacity); 260 // minCapacity is usually close to size, so this is a win: 261 elementData = Arrays.copyOf(elementData, newCapacity); 262 } 263 264 private static int hugeCapacity(int minCapacity) { 265 if (minCapacity < 0) // overflow 266 throw new OutOfMemoryError(); 267 return (minCapacity > MAX_ARRAY_SIZE) ? 268 Integer.MAX_VALUE : 269 MAX_ARRAY_SIZE; 270 } 271 272 /** 273 * Returns the number of elements in this list. 274 * 275 * @return the number of elements in this list 276 */ 277 public int size() { 278 return size; 279 } 280 281 /** 282 * Returns <tt>true</tt> if this list contains no elements. 283 * 284 * @return <tt>true</tt> if this list contains no elements 285 */ 286 public boolean isEmpty() { 287 return size == 0; 288 } 289 290 /** 291 * Returns <tt>true</tt> if this list contains the specified element. 292 * More formally, returns <tt>true</tt> if and only if this list contains 293 * at least one element <tt>e</tt> such that 294 * <tt>(o==null ? e==null : o.equals(e))</tt>. 295 * 296 * @param o element whose presence in this list is to be tested 297 * @return <tt>true</tt> if this list contains the specified element 298 */ 299 public boolean contains(Object o) { 300 return indexOf(o) >= 0; 301 } 302 303 /** 304 * Returns the index of the first occurrence of the specified element 305 * in this list, or -1 if this list does not contain the element. 306 * More formally, returns the lowest index <tt>i</tt> such that 307 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 308 * or -1 if there is no such index. 309 */ 310 public int indexOf(Object o) { 311 if (o == null) { 312 for (int i = 0; i < size; i++) 313 if (elementData[i]==null) 314 return i; 315 } else { 316 for (int i = 0; i < size; i++) 317 if (o.equals(elementData[i])) 318 return i; 319 } 320 return -1; 321 } 322 323 /** 324 * Returns the index of the last occurrence of the specified element 325 * in this list, or -1 if this list does not contain the element. 326 * More formally, returns the highest index <tt>i</tt> such that 327 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, 328 * or -1 if there is no such index. 329 */ 330 public int lastIndexOf(Object o) { 331 if (o == null) { 332 for (int i = size-1; i >= 0; i--) 333 if (elementData[i]==null) 334 return i; 335 } else { 336 for (int i = size-1; i >= 0; i--) 337 if (o.equals(elementData[i])) 338 return i; 339 } 340 return -1; 341 } 342 343 /** 344 * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The 345 * elements themselves are not copied.) 346 * 347 * @return a clone of this <tt>ArrayList</tt> instance 348 */ 349 public Object clone() { 350 try { 351 ArrayList<?> v = (ArrayList<?>) super.clone(); 352 v.elementData = Arrays.copyOf(elementData, size); 353 v.modCount = 0; 354 return v; 355 } catch (CloneNotSupportedException e) { 356 // this shouldn't happen, since we are Cloneable 357 throw new InternalError(e); 358 } 359 } 360 361 /** 362 * Returns an array containing all of the elements in this list 363 * in proper sequence (from first to last element). 364 * 365 * <p>The returned array will be "safe" in that no references to it are 366 * maintained by this list. (In other words, this method must allocate 367 * a new array). The caller is thus free to modify the returned array. 368 * 369 * <p>This method acts as bridge between array-based and collection-based 370 * APIs. 371 * 372 * @return an array containing all of the elements in this list in 373 * proper sequence 374 */ 375 public Object[] toArray() { 376 return Arrays.copyOf(elementData, size); 377 } 378 379 /** 380 * Returns an array containing all of the elements in this list in proper 381 * sequence (from first to last element); the runtime type of the returned 382 * array is that of the specified array. If the list fits in the 383 * specified array, it is returned therein. Otherwise, a new array is 384 * allocated with the runtime type of the specified array and the size of 385 * this list. 386 * 387 * <p>If the list fits in the specified array with room to spare 388 * (i.e., the array has more elements than the list), the element in 389 * the array immediately following the end of the collection is set to 390 * <tt>null</tt>. (This is useful in determining the length of the 391 * list <i>only</i> if the caller knows that the list does not contain 392 * any null elements.) 393 * 394 * @param a the array into which the elements of the list are to 395 * be stored, if it is big enough; otherwise, a new array of the 396 * same runtime type is allocated for this purpose. 397 * @return an array containing the elements of the list 398 * @throws ArrayStoreException if the runtime type of the specified array 399 * is not a supertype of the runtime type of every element in 400 * this list 401 * @throws NullPointerException if the specified array is null 402 */ 403 @SuppressWarnings("unchecked") 404 public <T> T[] toArray(T[] a) { 405 if (a.length < size) 406 // Make a new array of a's runtime type, but my contents: 407 return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 408 System.arraycopy(elementData, 0, a, 0, size); 409 if (a.length > size) 410 a[size] = null; 411 return a; 412 } 413 414 // Positional Access Operations 415 416 @SuppressWarnings("unchecked") 417 E elementData(int index) { 418 return (E) elementData[index]; 419 } 420 421 /** 422 * Returns the element at the specified position in this list. 423 * 424 * @param index index of the element to return 425 * @return the element at the specified position in this list 426 * @throws IndexOutOfBoundsException {@inheritDoc} 427 */ 428 public E get(int index) { 429 rangeCheck(index); 430 431 return elementData(index); 432 } 433 434 /** 435 * Replaces the element at the specified position in this list with 436 * the specified element. 437 * 438 * @param index index of the element to replace 439 * @param element element to be stored at the specified position 440 * @return the element previously at the specified position 441 * @throws IndexOutOfBoundsException {@inheritDoc} 442 */ 443 public E set(int index, E element) { 444 rangeCheck(index); 445 446 E oldValue = elementData(index); 447 elementData[index] = element; 448 return oldValue; 449 } 450 451 /** 452 * Appends the specified element to the end of this list. 453 * 454 * @param e element to be appended to this list 455 * @return <tt>true</tt> (as specified by {@link Collection#add}) 456 */ 457 public boolean add(E e) { 458 ensureCapacityInternal(size + 1); // Increments modCount!! 459 elementData[size++] = e; 460 return true; 461 } 462 463 /** 464 * Inserts the specified element at the specified position in this 465 * list. Shifts the element currently at that position (if any) and 466 * any subsequent elements to the right (adds one to their indices). 467 * 468 * @param index index at which the specified element is to be inserted 469 * @param element element to be inserted 470 * @throws IndexOutOfBoundsException {@inheritDoc} 471 */ 472 public void add(int index, E element) { 473 rangeCheckForAdd(index); 474 475 ensureCapacityInternal(size + 1); // Increments modCount!! 476 System.arraycopy(elementData, index, elementData, index + 1, 477 size - index); 478 elementData[index] = element; 479 size++; 480 } 481 482 /** 483 * Removes the element at the specified position in this list. 484 * Shifts any subsequent elements to the left (subtracts one from their 485 * indices). 486 * 487 * @param index the index of the element to be removed 488 * @return the element that was removed from the list 489 * @throws IndexOutOfBoundsException {@inheritDoc} 490 */ 491 public E remove(int index) { 492 rangeCheck(index); 493 494 modCount++; 495 E oldValue = elementData(index); 496 497 int numMoved = size - index - 1; 498 if (numMoved > 0) 499 System.arraycopy(elementData, index+1, elementData, index, 500 numMoved); 501 elementData[--size] = null; // clear to let GC do its work 502 503 return oldValue; 504 } 505 506 /** 507 * Removes the first occurrence of the specified element from this list, 508 * if it is present. If the list does not contain the element, it is 509 * unchanged. More formally, removes the element with the lowest index 510 * <tt>i</tt> such that 511 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> 512 * (if such an element exists). Returns <tt>true</tt> if this list 513 * contained the specified element (or equivalently, if this list 514 * changed as a result of the call). 515 * 516 * @param o element to be removed from this list, if present 517 * @return <tt>true</tt> if this list contained the specified element 518 */ 519 public boolean remove(Object o) { 520 if (o == null) { 521 for (int index = 0; index < size; index++) 522 if (elementData[index] == null) { 523 fastRemove(index); 524 return true; 525 } 526 } else { 527 for (int index = 0; index < size; index++) 528 if (o.equals(elementData[index])) { 529 fastRemove(index); 530 return true; 531 } 532 } 533 return false; 534 } 535 536 /* 537 * Private remove method that skips bounds checking and does not 538 * return the value removed. 539 */ 540 private void fastRemove(int index) { 541 modCount++; 542 int numMoved = size - index - 1; 543 if (numMoved > 0) 544 System.arraycopy(elementData, index+1, elementData, index, 545 numMoved); 546 elementData[--size] = null; // clear to let GC do its work 547 } 548 549 /** 550 * Removes all of the elements from this list. The list will 551 * be empty after this call returns. 552 */ 553 public void clear() { 554 modCount++; 555 556 // clear to let GC do its work 557 for (int i = 0; i < size; i++) 558 elementData[i] = null; 559 560 size = 0; 561 } 562 563 /** 564 * Appends all of the elements in the specified collection to the end of 565 * this list, in the order that they are returned by the 566 * specified collection's Iterator. The behavior of this operation is 567 * undefined if the specified collection is modified while the operation 568 * is in progress. (This implies that the behavior of this call is 569 * undefined if the specified collection is this list, and this 570 * list is nonempty.) 571 * 572 * @param c collection containing elements to be added to this list 573 * @return <tt>true</tt> if this list changed as a result of the call 574 * @throws NullPointerException if the specified collection is null 575 */ 576 public boolean addAll(Collection<? extends E> c) { 577 Object[] a = c.toArray(); 578 int numNew = a.length; 579 ensureCapacityInternal(size + numNew); // Increments modCount 580 System.arraycopy(a, 0, elementData, size, numNew); 581 size += numNew; 582 return numNew != 0; 583 } 584 585 /** 586 * Inserts all of the elements in the specified collection into this 587 * list, starting at the specified position. Shifts the element 588 * currently at that position (if any) and any subsequent elements to 589 * the right (increases their indices). The new elements will appear 590 * in the list in the order that they are returned by the 591 * specified collection's iterator. 592 * 593 * @param index index at which to insert the first element from the 594 * specified collection 595 * @param c collection containing elements to be added to this list 596 * @return <tt>true</tt> if this list changed as a result of the call 597 * @throws IndexOutOfBoundsException {@inheritDoc} 598 * @throws NullPointerException if the specified collection is null 599 */ 600 public boolean addAll(int index, Collection<? extends E> c) { 601 rangeCheckForAdd(index); 602 603 Object[] a = c.toArray(); 604 int numNew = a.length; 605 ensureCapacityInternal(size + numNew); // Increments modCount 606 607 int numMoved = size - index; 608 if (numMoved > 0) 609 System.arraycopy(elementData, index, elementData, index + numNew, 610 numMoved); 611 612 System.arraycopy(a, 0, elementData, index, numNew); 613 size += numNew; 614 return numNew != 0; 615 } 616 617 /** 618 * Removes from this list all of the elements whose index is between 619 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. 620 * Shifts any succeeding elements to the left (reduces their index). 621 * This call shortens the list by {@code (toIndex - fromIndex)} elements. 622 * (If {@code toIndex==fromIndex}, this operation has no effect.) 623 * 624 * @throws IndexOutOfBoundsException if {@code fromIndex} or 625 * {@code toIndex} is out of range 626 * ({@code fromIndex < 0 || 627 * fromIndex >= size() || 628 * toIndex > size() || 629 * toIndex < fromIndex}) 630 */ 631 protected void removeRange(int fromIndex, int toIndex) { 632 modCount++; 633 int numMoved = size - toIndex; 634 System.arraycopy(elementData, toIndex, elementData, fromIndex, 635 numMoved); 636 637 // clear to let GC do its work 638 int newSize = size - (toIndex-fromIndex); 639 for (int i = newSize; i < size; i++) { 640 elementData[i] = null; 641 } 642 size = newSize; 643 } 644 645 /** 646 * Checks if the given index is in range. If not, throws an appropriate 647 * runtime exception. This method does *not* check if the index is 648 * negative: It is always used immediately prior to an array access, 649 * which throws an ArrayIndexOutOfBoundsException if index is negative. 650 */ 651 private void rangeCheck(int index) { 652 if (index >= size) 653 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 654 } 655 656 /** 657 * A version of rangeCheck used by add and addAll. 658 */ 659 private void rangeCheckForAdd(int index) { 660 if (index > size || index < 0) 661 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 662 } 663 664 /** 665 * Constructs an IndexOutOfBoundsException detail message. 666 * Of the many possible refactorings of the error handling code, 667 * this "outlining" performs best with both server and client VMs. 668 */ 669 private String outOfBoundsMsg(int index) { 670 return "Index: "+index+", Size: "+size; 671 } 672 673 /** 674 * Removes from this list all of its elements that are contained in the 675 * specified collection. 676 * 677 * @param c collection containing elements to be removed from this list 678 * @return {@code true} if this list changed as a result of the call 679 * @throws ClassCastException if the class of an element of this list 680 * is incompatible with the specified collection 681 * (<a href="Collection.html#optional-restrictions">optional</a>) 682 * @throws NullPointerException if this list contains a null element and the 683 * specified collection does not permit null elements 684 * (<a href="Collection.html#optional-restrictions">optional</a>), 685 * or if the specified collection is null 686 * @see Collection#contains(Object) 687 */ 688 public boolean removeAll(Collection<?> c) { 689 Objects.requireNonNull(c); 690 return batchRemove(c, false); 691 } 692 693 /** 694 * Retains only the elements in this list that are contained in the 695 * specified collection. In other words, removes from this list all 696 * of its elements that are not contained in the specified collection. 697 * 698 * @param c collection containing elements to be retained in this list 699 * @return {@code true} if this list changed as a result of the call 700 * @throws ClassCastException if the class of an element of this list 701 * is incompatible with the specified collection 702 * (<a href="Collection.html#optional-restrictions">optional</a>) 703 * @throws NullPointerException if this list contains a null element and the 704 * specified collection does not permit null elements 705 * (<a href="Collection.html#optional-restrictions">optional</a>), 706 * or if the specified collection is null 707 * @see Collection#contains(Object) 708 */ 709 public boolean retainAll(Collection<?> c) { 710 Objects.requireNonNull(c); 711 return batchRemove(c, true); 712 } 713 714 private boolean batchRemove(Collection<?> c, boolean complement) { 715 final Object[] elementData = this.elementData; 716 int r = 0, w = 0; 717 boolean modified = false; 718 try { 719 for (; r < size; r++) 720 if (c.contains(elementData[r]) == complement) 721 elementData[w++] = elementData[r]; 722 } finally { 723 // Preserve behavioral compatibility with AbstractCollection, 724 // even if c.contains() throws. 725 if (r != size) { 726 System.arraycopy(elementData, r, 727 elementData, w, 728 size - r); 729 w += size - r; 730 } 731 if (w != size) { 732 // clear to let GC do its work 733 for (int i = w; i < size; i++) 734 elementData[i] = null; 735 modCount += size - w; 736 size = w; 737 modified = true; 738 } 739 } 740 return modified; 741 } 742 743 /** 744 * Save the state of the <tt>ArrayList</tt> instance to a stream (that 745 * is, serialize it). 746 * 747 * @serialData The length of the array backing the <tt>ArrayList</tt> 748 * instance is emitted (int), followed by all of its elements 749 * (each an <tt>Object</tt>) in the proper order. 750 */ 751 private void writeObject(java.io.ObjectOutputStream s) 752 throws java.io.IOException{ 753 // Write out element count, and any hidden stuff 754 int expectedModCount = modCount; 755 s.defaultWriteObject(); 756 757 // Write out size as capacity for behavioural compatibility with clone() 758 s.writeInt(size); 759 760 // Write out all elements in the proper order. 761 for (int i=0; i<size; i++) { 762 s.writeObject(elementData[i]); 763 } 764 765 if (modCount != expectedModCount) { 766 throw new ConcurrentModificationException(); 767 } 768 } 769 770 /** 771 * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is, 772 * deserialize it). 773 */ 774 private void readObject(java.io.ObjectInputStream s) 775 throws java.io.IOException, ClassNotFoundException { 776 elementData = EMPTY_ELEMENTDATA; 777 778 // Read in size, and any hidden stuff 779 s.defaultReadObject(); 780 781 // Read in capacity 782 s.readInt(); // ignored 783 784 if (size > 0) { 785 // be like clone(), allocate array based upon size not capacity 786 ensureCapacityInternal(size); 787 788 Object[] a = elementData; 789 // Read in all elements in the proper order. 790 for (int i=0; i<size; i++) { 791 a[i] = s.readObject(); 792 } 793 } 794 } 795 796 /** 797 * Returns a list iterator over the elements in this list (in proper 798 * sequence), starting at the specified position in the list. 799 * The specified index indicates the first element that would be 800 * returned by an initial call to {@link ListIterator#next next}. 801 * An initial call to {@link ListIterator#previous previous} would 802 * return the element with the specified index minus one. 803 * 804 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. 805 * 806 * @throws IndexOutOfBoundsException {@inheritDoc} 807 */ 808 public ListIterator<E> listIterator(int index) { 809 if (index < 0 || index > size) 810 throw new IndexOutOfBoundsException("Index: "+index); 811 return new ListItr(index); 812 } 813 814 /** 815 * Returns a list iterator over the elements in this list (in proper 816 * sequence). 817 * 818 * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>. 819 * 820 * @see #listIterator(int) 821 */ 822 public ListIterator<E> listIterator() { 823 return new ListItr(0); 824 } 825 826 /** 827 * Returns an iterator over the elements in this list in proper sequence. 828 * 829 * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. 830 * 831 * @return an iterator over the elements in this list in proper sequence 832 */ 833 public Iterator<E> iterator() { 834 return new Itr(); 835 } 836 837 /** 838 * An optimized version of AbstractList.Itr 839 */ 840 private class Itr implements Iterator<E> { 841 int cursor; // index of next element to return 842 int lastRet = -1; // index of last element returned; -1 if no such 843 int expectedModCount = modCount; 844 845 public boolean hasNext() { 846 return cursor != size; 847 } 848 849 @SuppressWarnings("unchecked") 850 public E next() { 851 checkForComodification(); 852 int i = cursor; 853 if (i >= size) 854 throw new NoSuchElementException(); 855 Object[] elementData = ArrayList.this.elementData; 856 if (i >= elementData.length) 857 throw new ConcurrentModificationException(); 858 cursor = i + 1; 859 return (E) elementData[lastRet = i]; 860 } 861 862 public void remove() { 863 if (lastRet < 0) 864 throw new IllegalStateException(); 865 checkForComodification(); 866 867 try { 868 ArrayList.this.remove(lastRet); 869 cursor = lastRet; 870 lastRet = -1; 871 expectedModCount = modCount; 872 } catch (IndexOutOfBoundsException ex) { 873 throw new ConcurrentModificationException(); 874 } 875 } 876 877 @Override 878 @SuppressWarnings("unchecked") 879 public void forEachRemaining(Consumer<? super E> consumer) { 880 Objects.requireNonNull(consumer); 881 final int size = ArrayList.this.size; 882 int i = cursor; 883 if (i >= size) { 884 return; 885 } 886 final Object[] elementData = ArrayList.this.elementData; 887 if (i >= elementData.length) { 888 throw new ConcurrentModificationException(); 889 } 890 while (i != size && modCount == expectedModCount) { 891 consumer.accept((E) elementData[i++]); 892 } 893 // update once at end of iteration to reduce heap write traffic 894 cursor = i; 895 lastRet = i - 1; 896 checkForComodification(); 897 } 898 899 final void checkForComodification() { 900 if (modCount != expectedModCount) 901 throw new ConcurrentModificationException(); 902 } 903 } 904 905 /** 906 * An optimized version of AbstractList.ListItr 907 */ 908 private class ListItr extends Itr implements ListIterator<E> { 909 ListItr(int index) { 910 super(); 911 cursor = index; 912 } 913 914 public boolean hasPrevious() { 915 return cursor != 0; 916 } 917 918 public int nextIndex() { 919 return cursor; 920 } 921 922 public int previousIndex() { 923 return cursor - 1; 924 } 925 926 @SuppressWarnings("unchecked") 927 public E previous() { 928 checkForComodification(); 929 int i = cursor - 1; 930 if (i < 0) 931 throw new NoSuchElementException(); 932 Object[] elementData = ArrayList.this.elementData; 933 if (i >= elementData.length) 934 throw new ConcurrentModificationException(); 935 cursor = i; 936 return (E) elementData[lastRet = i]; 937 } 938 939 public void set(E e) { 940 if (lastRet < 0) 941 throw new IllegalStateException(); 942 checkForComodification(); 943 944 try { 945 ArrayList.this.set(lastRet, e); 946 } catch (IndexOutOfBoundsException ex) { 947 throw new ConcurrentModificationException(); 948 } 949 } 950 951 public void add(E e) { 952 checkForComodification(); 953 954 try { 955 int i = cursor; 956 ArrayList.this.add(i, e); 957 cursor = i + 1; 958 lastRet = -1; 959 expectedModCount = modCount; 960 } catch (IndexOutOfBoundsException ex) { 961 throw new ConcurrentModificationException(); 962 } 963 } 964 } 965 966 /** 967 * Returns a view of the portion of this list between the specified 968 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If 969 * {@code fromIndex} and {@code toIndex} are equal, the returned list is 970 * empty.) The returned list is backed by this list, so non-structural 971 * changes in the returned list are reflected in this list, and vice-versa. 972 * The returned list supports all of the optional list operations. 973 * 974 * <p>This method eliminates the need for explicit range operations (of 975 * the sort that commonly exist for arrays). Any operation that expects 976 * a list can be used as a range operation by passing a subList view 977 * instead of a whole list. For example, the following idiom 978 * removes a range of elements from a list: 979 * <pre> 980 * list.subList(from, to).clear(); 981 * </pre> 982 * Similar idioms may be constructed for {@link #indexOf(Object)} and 983 * {@link #lastIndexOf(Object)}, and all of the algorithms in the 984 * {@link Collections} class can be applied to a subList. 985 * 986 * <p>The semantics of the list returned by this method become undefined if 987 * the backing list (i.e., this list) is <i>structurally modified</i> in 988 * any way other than via the returned list. (Structural modifications are 989 * those that change the size of this list, or otherwise perturb it in such 990 * a fashion that iterations in progress may yield incorrect results.) 991 * 992 * @throws IndexOutOfBoundsException {@inheritDoc} 993 * @throws IllegalArgumentException {@inheritDoc} 994 */ 995 public List<E> subList(int fromIndex, int toIndex) { 996 subListRangeCheck(fromIndex, toIndex, size); 997 return new SubList(this, 0, fromIndex, toIndex); 998 } 999 1000 static void subListRangeCheck(int fromIndex, int toIndex, int size) { 1001 if (fromIndex < 0) 1002 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); 1003 if (toIndex > size) 1004 throw new IndexOutOfBoundsException("toIndex = " + toIndex); 1005 if (fromIndex > toIndex) 1006 throw new IllegalArgumentException("fromIndex(" + fromIndex + 1007 ") > toIndex(" + toIndex + ")"); 1008 } 1009 1010 private class SubList extends AbstractList<E> implements RandomAccess { 1011 private final AbstractList<E> parent; 1012 private final int parentOffset; 1013 private final int offset; 1014 int size; 1015 1016 SubList(AbstractList<E> parent, 1017 int offset, int fromIndex, int toIndex) { 1018 this.parent = parent; 1019 this.parentOffset = fromIndex; 1020 this.offset = offset + fromIndex; 1021 this.size = toIndex - fromIndex; 1022 this.modCount = ArrayList.this.modCount; 1023 } 1024 1025 public E set(int index, E e) { 1026 rangeCheck(index); 1027 checkForComodification(); 1028 E oldValue = ArrayList.this.elementData(offset + index); 1029 ArrayList.this.elementData[offset + index] = e; 1030 return oldValue; 1031 } 1032 1033 public E get(int index) { 1034 rangeCheck(index); 1035 checkForComodification(); 1036 return ArrayList.this.elementData(offset + index); 1037 } 1038 1039 public int size() { 1040 checkForComodification(); 1041 return this.size; 1042 } 1043 1044 public void add(int index, E e) { 1045 rangeCheckForAdd(index); 1046 checkForComodification(); 1047 parent.add(parentOffset + index, e); 1048 this.modCount = parent.modCount; 1049 this.size++; 1050 } 1051 1052 public E remove(int index) { 1053 rangeCheck(index); 1054 checkForComodification(); 1055 E result = parent.remove(parentOffset + index); 1056 this.modCount = parent.modCount; 1057 this.size--; 1058 return result; 1059 } 1060 1061 protected void removeRange(int fromIndex, int toIndex) { 1062 checkForComodification(); 1063 parent.removeRange(parentOffset + fromIndex, 1064 parentOffset + toIndex); 1065 this.modCount = parent.modCount; 1066 this.size -= toIndex - fromIndex; 1067 } 1068 1069 public boolean addAll(Collection<? extends E> c) { 1070 return addAll(this.size, c); 1071 } 1072 1073 public boolean addAll(int index, Collection<? extends E> c) { 1074 rangeCheckForAdd(index); 1075 int cSize = c.size(); 1076 if (cSize==0) 1077 return false; 1078 1079 checkForComodification(); 1080 parent.addAll(parentOffset + index, c); 1081 this.modCount = parent.modCount; 1082 this.size += cSize; 1083 return true; 1084 } 1085 1086 public Iterator<E> iterator() { 1087 return listIterator(); 1088 } 1089 1090 public ListIterator<E> listIterator(final int index) { 1091 checkForComodification(); 1092 rangeCheckForAdd(index); 1093 final int offset = this.offset; 1094 1095 return new ListIterator<E>() { 1096 int cursor = index; 1097 int lastRet = -1; 1098 int expectedModCount = ArrayList.this.modCount; 1099 1100 public boolean hasNext() { 1101 return cursor != SubList.this.size; 1102 } 1103 1104 @SuppressWarnings("unchecked") 1105 public E next() { 1106 checkForComodification(); 1107 int i = cursor; 1108 if (i >= SubList.this.size) 1109 throw new NoSuchElementException(); 1110 Object[] elementData = ArrayList.this.elementData; 1111 if (offset + i >= elementData.length) 1112 throw new ConcurrentModificationException(); 1113 cursor = i + 1; 1114 return (E) elementData[offset + (lastRet = i)]; 1115 } 1116 1117 public boolean hasPrevious() { 1118 return cursor != 0; 1119 } 1120 1121 @SuppressWarnings("unchecked") 1122 public E previous() { 1123 checkForComodification(); 1124 int i = cursor - 1; 1125 if (i < 0) 1126 throw new NoSuchElementException(); 1127 Object[] elementData = ArrayList.this.elementData; 1128 if (offset + i >= elementData.length) 1129 throw new ConcurrentModificationException(); 1130 cursor = i; 1131 return (E) elementData[offset + (lastRet = i)]; 1132 } 1133 1134 @SuppressWarnings("unchecked") 1135 public void forEachRemaining(Consumer<? super E> consumer) { 1136 Objects.requireNonNull(consumer); 1137 final int size = SubList.this.size; 1138 int i = cursor; 1139 if (i >= size) { 1140 return; 1141 } 1142 final Object[] elementData = ArrayList.this.elementData; 1143 if (offset + i >= elementData.length) { 1144 throw new ConcurrentModificationException(); 1145 } 1146 while (i != size && modCount == expectedModCount) { 1147 consumer.accept((E) elementData[offset + (i++)]); 1148 } 1149 // update once at end of iteration to reduce heap write traffic 1150 lastRet = cursor = i; 1151 checkForComodification(); 1152 } 1153 1154 public int nextIndex() { 1155 return cursor; 1156 } 1157 1158 public int previousIndex() { 1159 return cursor - 1; 1160 } 1161 1162 public void remove() { 1163 if (lastRet < 0) 1164 throw new IllegalStateException(); 1165 checkForComodification(); 1166 1167 try { 1168 SubList.this.remove(lastRet); 1169 cursor = lastRet; 1170 lastRet = -1; 1171 expectedModCount = ArrayList.this.modCount; 1172 } catch (IndexOutOfBoundsException ex) { 1173 throw new ConcurrentModificationException(); 1174 } 1175 } 1176 1177 public void set(E e) { 1178 if (lastRet < 0) 1179 throw new IllegalStateException(); 1180 checkForComodification(); 1181 1182 try { 1183 ArrayList.this.set(offset + lastRet, e); 1184 } catch (IndexOutOfBoundsException ex) { 1185 throw new ConcurrentModificationException(); 1186 } 1187 } 1188 1189 public void add(E e) { 1190 checkForComodification(); 1191 1192 try { 1193 int i = cursor; 1194 SubList.this.add(i, e); 1195 cursor = i + 1; 1196 lastRet = -1; 1197 expectedModCount = ArrayList.this.modCount; 1198 } catch (IndexOutOfBoundsException ex) { 1199 throw new ConcurrentModificationException(); 1200 } 1201 } 1202 1203 final void checkForComodification() { 1204 if (expectedModCount != ArrayList.this.modCount) 1205 throw new ConcurrentModificationException(); 1206 } 1207 }; 1208 } 1209 1210 public List<E> subList(int fromIndex, int toIndex) { 1211 subListRangeCheck(fromIndex, toIndex, size); 1212 return new SubList(this, offset, fromIndex, toIndex); 1213 } 1214 1215 private void rangeCheck(int index) { 1216 if (index < 0 || index >= this.size) 1217 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 1218 } 1219 1220 private void rangeCheckForAdd(int index) { 1221 if (index < 0 || index > this.size) 1222 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 1223 } 1224 1225 private String outOfBoundsMsg(int index) { 1226 return "Index: "+index+", Size: "+this.size; 1227 } 1228 1229 private void checkForComodification() { 1230 if (ArrayList.this.modCount != this.modCount) 1231 throw new ConcurrentModificationException(); 1232 } 1233 1234 public Spliterator<E> spliterator() { 1235 checkForComodification(); 1236 return new ArrayListSpliterator<E>(ArrayList.this, offset, 1237 offset + this.size, this.modCount); 1238 } 1239 } 1240 1241 @Override 1242 public void forEach(Consumer<? super E> action) { 1243 Objects.requireNonNull(action); 1244 final int expectedModCount = modCount; 1245 @SuppressWarnings("unchecked") 1246 final E[] elementData = (E[]) this.elementData; 1247 final int size = this.size; 1248 for (int i=0; modCount == expectedModCount && i < size; i++) { 1249 action.accept(elementData[i]); 1250 } 1251 if (modCount != expectedModCount) { 1252 throw new ConcurrentModificationException(); 1253 } 1254 } 1255 1256 /** 1257 * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em> 1258 * and <em>fail-fast</em> {@link Spliterator} over the elements in this 1259 * list. 1260 * 1261 * <p>The {@code Spliterator} reports {@link Spliterator#SIZED}, 1262 * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}. 1263 * Overriding implementations should document the reporting of additional 1264 * characteristic values. 1265 * 1266 * @return a {@code Spliterator} over the elements in this list 1267 * @since 1.8 1268 */ 1269 @Override 1270 public Spliterator<E> spliterator() { 1271 return new ArrayListSpliterator<>(this, 0, -1, 0); 1272 } 1273 1274 /** Index-based split-by-two, lazily initialized Spliterator */ 1275 static final class ArrayListSpliterator<E> implements Spliterator<E> { 1276 1277 /* 1278 * If ArrayLists were immutable, or structurally immutable (no 1279 * adds, removes, etc), we could implement their spliterators 1280 * with Arrays.spliterator. Instead we detect as much 1281 * interference during traversal as practical without 1282 * sacrificing much performance. We rely primarily on 1283 * modCounts. These are not guaranteed to detect concurrency 1284 * violations, and are sometimes overly conservative about 1285 * within-thread interference, but detect enough problems to 1286 * be worthwhile in practice. To carry this out, we (1) lazily 1287 * initialize fence and expectedModCount until the latest 1288 * point that we need to commit to the state we are checking 1289 * against; thus improving precision. (This doesn't apply to 1290 * SubLists, that create spliterators with current non-lazy 1291 * values). (2) We perform only a single 1292 * ConcurrentModificationException check at the end of forEach 1293 * (the most performance-sensitive method). When using forEach 1294 * (as opposed to iterators), we can normally only detect 1295 * interference after actions, not before. Further 1296 * CME-triggering checks apply to all other possible 1297 * violations of assumptions for example null or too-small 1298 * elementData array given its size(), that could only have 1299 * occurred due to interference. This allows the inner loop 1300 * of forEach to run without any further checks, and 1301 * simplifies lambda-resolution. While this does entail a 1302 * number of checks, note that in the common case of 1303 * list.stream().forEach(a), no checks or other computation 1304 * occur anywhere other than inside forEach itself. The other 1305 * less-often-used methods cannot take advantage of most of 1306 * these streamlinings. 1307 */ 1308 1309 private final ArrayList<E> list; 1310 private int index; // current index, modified on advance/split 1311 private int fence; // -1 until used; then one past last index 1312 private int expectedModCount; // initialized when fence set 1313 1314 /** Create new spliterator covering the given range */ 1315 ArrayListSpliterator(ArrayList<E> list, int origin, int fence, 1316 int expectedModCount) { 1317 this.list = list; // OK if null unless traversed 1318 this.index = origin; 1319 this.fence = fence; 1320 this.expectedModCount = expectedModCount; 1321 } 1322 1323 private int getFence() { // initialize fence to size on first use 1324 int hi; // (a specialized variant appears in method forEach) 1325 ArrayList<E> lst; 1326 if ((hi = fence) < 0) { 1327 if ((lst = list) == null) 1328 hi = fence = 0; 1329 else { 1330 expectedModCount = lst.modCount; 1331 hi = fence = lst.size; 1332 } 1333 } 1334 return hi; 1335 } 1336 1337 public ArrayListSpliterator<E> trySplit() { 1338 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; 1339 return (lo >= mid) ? null : // divide range in half unless too small 1340 new ArrayListSpliterator<E>(list, lo, index = mid, 1341 expectedModCount); 1342 } 1343 1344 public boolean tryAdvance(Consumer<? super E> action) { 1345 if (action == null) 1346 throw new NullPointerException(); 1347 int hi = getFence(), i = index; 1348 if (i < hi) { 1349 index = i + 1; 1350 @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; 1351 action.accept(e); 1352 if (list.modCount != expectedModCount) 1353 throw new ConcurrentModificationException(); 1354 return true; 1355 } 1356 return false; 1357 } 1358 1359 public void forEachRemaining(Consumer<? super E> action) { 1360 int i, hi, mc; // hoist accesses and checks from loop 1361 ArrayList<E> lst; Object[] a; 1362 if (action == null) 1363 throw new NullPointerException(); 1364 if ((lst = list) != null && (a = lst.elementData) != null) { 1365 if ((hi = fence) < 0) { 1366 mc = lst.modCount; 1367 hi = lst.size; 1368 } 1369 else 1370 mc = expectedModCount; 1371 if ((i = index) >= 0 && (index = hi) <= a.length) { 1372 for (; i < hi; ++i) { 1373 @SuppressWarnings("unchecked") E e = (E) a[i]; 1374 action.accept(e); 1375 } 1376 if (lst.modCount == mc) 1377 return; 1378 } 1379 } 1380 throw new ConcurrentModificationException(); 1381 } 1382 1383 public long estimateSize() { 1384 return (long) (getFence() - index); 1385 } 1386 1387 public int characteristics() { 1388 return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; 1389 } 1390 } 1391 1392 @Override 1393 public boolean removeIf(Predicate<? super E> filter) { 1394 Objects.requireNonNull(filter); 1395 // figure out which elements are to be removed 1396 // any exception thrown from the filter predicate at this stage 1397 // will leave the collection unmodified 1398 int removeCount = 0; 1399 final BitSet removeSet = new BitSet(size); 1400 final int expectedModCount = modCount; 1401 final int size = this.size; 1402 for (int i=0; modCount == expectedModCount && i < size; i++) { 1403 @SuppressWarnings("unchecked") 1404 final E element = (E) elementData[i]; 1405 if (filter.test(element)) { 1406 removeSet.set(i); 1407 removeCount++; 1408 } 1409 } 1410 if (modCount != expectedModCount) { 1411 throw new ConcurrentModificationException(); 1412 } 1413 1414 // shift surviving elements left over the spaces left by removed elements 1415 final boolean anyToRemove = removeCount > 0; 1416 if (anyToRemove) { 1417 final int newSize = size - removeCount; 1418 for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { 1419 i = removeSet.nextClearBit(i); 1420 elementData[j] = elementData[i]; 1421 } 1422 for (int k=newSize; k < size; k++) { 1423 elementData[k] = null; // Let gc do its work 1424 } 1425 this.size = newSize; 1426 if (modCount != expectedModCount) { 1427 throw new ConcurrentModificationException(); 1428 } 1429 modCount++; 1430 } 1431 1432 return anyToRemove; 1433 } 1434 1435 @Override 1436 @SuppressWarnings("unchecked") 1437 public void replaceAll(UnaryOperator<E> operator) { 1438 Objects.requireNonNull(operator); 1439 final int expectedModCount = modCount; 1440 final int size = this.size; 1441 for (int i=0; modCount == expectedModCount && i < size; i++) { 1442 elementData[i] = operator.apply((E) elementData[i]); 1443 } 1444 if (modCount != expectedModCount) { 1445 throw new ConcurrentModificationException(); 1446 } 1447 modCount++; 1448 } 1449 1450 @Override 1451 @SuppressWarnings("unchecked") 1452 public void sort(Comparator<? super E> c) { 1453 final int expectedModCount = modCount; 1454 Arrays.sort((E[]) elementData, 0, size, c); 1455 if (modCount != expectedModCount) { 1456 throw new ConcurrentModificationException(); 1457 } 1458 modCount++; 1459 } 1460 }
贴上类的结构图:
内容太长,分2次截图。
直接看看里面有些什么吧!
(1)存放集合数据的数组!
private static final Object[] EMPTY_ELEMENTDATA = {};//用于空实例的共享空数组实例。 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//扩展数组 transient Object[] elementData;//存放数据的原始数组
(2)实例化集合对象
//【1】传入集合大小,初始化集合容量,不够时自动扩展 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } //【2】直接拿到集合实例,不固定集合大小 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //【3】用另外一个集合来实例化当前集合 public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { this.elementData = EMPTY_ELEMENTDATA; } }
分析说明一下:
(1)如果采用【1】中方式拿到集合对象,那么当超过设置的初始容量的时候是如何扩容的呢?
看下面这个例子:
1 public static void main(String[] args) throws Exception { 2 List list=new ArrayList(2); 3 System.out.println("扩展前集合容量1:"+getCapacity(list)); 4 list.add(1); 5 list.add(2); 6 System.out.println("扩展前集合容量2:"+getCapacity(list)); 7 list.add(3); 8 list.add(4); 9 System.out.println("扩展后集合容量3:"+getCapacity(list)); 10 list.add(5); 11 list.add(6); 12 System.out.println("扩展后集合容量4:"+getCapacity(list)); 13 list.add(7); 14 list.add(8); 15 System.out.println("扩展后集合容量5:"+getCapacity(list)); 16 list.add(9); 17 System.out.println("扩展后集合容量6:"+getCapacity(list)); 18 list.add(10); 19 System.out.println("扩展后集合容量7:"+getCapacity(list)); 20 for(Object o:list){ 21 System.out.println(o); 22 } 23 System.out.println("扩展后集合容量8:"+getCapacity(list)); 24 } 25 //反射拿到当前集合保存数据的数组的容量 26 static int getCapacity(List<?> l) throws Exception { 27 Field dataField = ArrayList.class.getDeclaredField("elementData"); 28 dataField.setAccessible(true); 29 return ((Object[]) dataField.get(l)).length; 30 }
输出结果:
扩展前集合容量1:2
扩展前集合容量2:2
扩展后集合容量3:4
扩展后集合容量4:6
扩展后集合容量5:9
扩展后集合容量6:9
扩展后集合容量7:13
1
2
3
4
5
6
7
8
9
10
扩展后集合容量8:13
从结果上,可以知道,扩展容量并不是均匀扩展的(每次都递增相同的容量),而是发生着变化的,那么这种变化规则是怎么样的呢?
继续分析一下源码中是怎么定义的:
1 //将指定的元素追加到列表的末尾 2 public boolean add(E e) { 3 ensureCapacityInternal(size + 1); // 增量模式计数!! 4 elementData[size++] = e; 5 return true; 6 } 7 //确定内部容量的方法 8 private void ensureCapacityInternal(int minCapacity) { 9 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 11 } 12 ensureExplicitCapacity(minCapacity); 13 } 14 private void ensureExplicitCapacity(int minCapacity) { 15 modCount++; 16 //判断当前集合是否超多最大容量,即是否有容量溢出现象 17 if (minCapacity - elementData.length > 0) 18 grow(minCapacity); 19 } 20 //集合内部维护的是数组扩容 21 private void grow(int minCapacity) { 22 int oldCapacity = elementData.length;//拿到当前集合大小 23 int newCapacity = oldCapacity + (oldCapacity >> 1);//计算集合新的容量大小 24 if (newCapacity - minCapacity < 0) 25 newCapacity = minCapacity; 26 if (newCapacity - MAX_ARRAY_SIZE > 0) 27 newCapacity = hugeCapacity(minCapacity); 28 //复制旧集合数据到新的集合中(内部维护的数组扩容-产生新的数组) 29 elementData = Arrays.copyOf(elementData, newCapacity); 30 }
那么在详细看以下2行代码是如何计算增加的容量的吧:
int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);
简单说明一下:“>>”运算符
>>运算规则:按二进制形式把所有的数字向右移动对应巍峨位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1.
语法格式:
需要移位的数字 >> 移位的次数
例如11 >> 2,则是将数字11右移2位
计算过程:11的二进制形式为:0000 0000 0000 0000 0000 0000 0000 1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0000 0000 0000 0000 0000 0000 0000 0010.转换为十进制是3.数学意义:右移一位相当于除2,右移n位相当于除以2的n次方。
举一个简答的例子:
1 public static void main(String[] args) throws Exception { 2 for(int i=0;i<=10;i++){ 3 System.out.println("******当前i="+i+"***********"); 4 System.out.println("递增数值:"+((i>>1))); 5 System.out.println("递增数后值:"+(i+(i>>1))); 6 } 7 }
运行结果:
******当前i=0*********** 递增数值:0 递增数后值:0 ******当前i=1*********** 递增数值:0 递增数后值:1 ******当前i=2*********** 递增数值:1 递增数后值:3 ******当前i=3*********** 递增数值:1 递增数后值:4 ******当前i=4*********** 递增数值:2 递增数后值:6 ******当前i=5*********** 递增数值:2 递增数后值:7 ******当前i=6*********** 递增数值:3 递增数后值:9 ******当前i=7*********** 递增数值:3 递增数后值:10 ******当前i=8*********** 递增数值:4 递增数后值:12 ******当前i=9*********** 递增数值:4 递增数后值:13 ******当前i=10*********** 递增数值:5 递增数后值:15
分析可以知道:每次递增的数值为:源数值的一半,且向下取整得到的数值。
(3)如何添加数据待集合中
ArrayList实现类中提供了2种方法,供添加数据使用:
public boolean add(E e) {//【1】直接在集合末尾添加一个数据 ensureCapacityInternal(size + 1); // 判断数据是否会溢出 elementData[size++] = e; return true; } public void add(int index, E element) {//【2】添加一个数据到集合的指定位置 rangeCheckForAdd(index);//检查位置是否合法 ensureCapacityInternal(size + 1); // 判断数据是否会溢出 System.arraycopy(elementData, index, elementData, index + 1,//System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制 size - index); elementData[index] = element; size++; }
方法【1】直接在集合末尾添加一个数据,上面已经给出了分析,这里就不在赘述了,那么来看一下方法【2】是怎么处理的!
(1)在指定位置添加一个数据,这个指定的位置,就需要检查是否合法:
rangeCheckForAdd(index);//检查位置是否合法
private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
(2)然后就是判断,如果新增了这个元素,会不会导致整个数组的数据溢出,如果会导致溢出现象,则要扩容数组。
具体的方法上面已经给出分析:这里再放一遍代码
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
(3)此时,位置索引值合法,数组也不会溢出了,就开始要实现如何插入。
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
上面这句代码:
System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制。其函数原型是:
public static void (Object src, int srcPos, Object dest, int destPos, int length)
参数说明:
src:源数组; srcPos:源数组要复制的起始位置;
dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
注意:src and dest都必须是同类型或者可以进行转换类型的数组.
有趣的是这个函数可以实现自己到自己复制,比如:
int[] fun ={0,1,2,3,4,5,6};
System.arraycopy(fun,0,fun,3,3);
则结果为:{0,1,2,0,1,2,6};
实现过程是这样的,先生成一个长度为length的临时数组,将fun数组中srcPos
到srcPos+length-1之间的数据拷贝到临时数组中,再执行System.arraycopy(临时数组,0,fun,3,3).
(4)实现了,指定位置之后(包含指定位置)的数据,向后移动的功能后,开始在指定的位置插入数据了。并且数据长度+1
elementData[index] = element;
size++;
(4)如何从集合中删除一个数据
ArrayList实现类中提供了2种方法,供删除数据使用:
public E remove(int index) {//【1】删除指定位置的数据 rangeCheck(index);//检查位置是否合法 modCount++; E oldValue = elementData(index);//拿到指定位置的数据 int numMoved = size - index - 1;//判断当前删除的位置是否是最后一位,如果是,则不需要移动数组元素,否则就需要移动 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; //置空该位置的数据 return oldValue; } public boolean remove(Object o) {//【2】删除指定的数据 if (o == null) {//当前要删除的数据为null for (int index = 0; index < size; index++) if (elementData[index] == null) {//遍历数组容量,拿到要删除数据的位置索引值 fastRemove(index);//调用删除元素的方法 return true; } } else {//当前要删除的数据不为null for (int index = 0; index < size; index++) if (o.equals(elementData[index])) {//遍历数组容量,拿到要删除数据的位置索引值 fastRemove(index);//调用删除元素的方法 return true; } } return false; } private void fastRemove(int index) {//快速删除指定位置的元素 modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work } private void rangeCheck(int index) {//判断当前位置的索引值是否合法 if (index >= size)//要删除的数据的位置不可超过数组容量,说明:如果过小的话,也会造成异常的发生 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
总结一下;
(1)具体如何删除集合数据,上面代码+说明已经很明显了,这里也不在赘述了。
有意思的是:
private void rangeCheck(int index) {//判断当前位置的索引值是否合法 if (index >= size)//要删除的数据的位置不可超过数组容量,说明:如果过小的话,也会造成异常的发生 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
在删除指定位置的数据的时候,对这个位置索引值做了合法性判断。但是只做了上限判断,下限判断 没有做。
(1)当索引值超过数组上限容量的时候,会抛出:throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
(2)当索引值低于数组下限容量值0的时候,如何处理呢?
public static void main(String[] args) throws Exception { List alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10); alist.remove(-1); }
运行结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at com.xfwl.test.Test4.main(Test4.java:17)
分析说明:
根据运行结果,发现的确会抛出异常,但是并不是在ArrayList这个实现子类中抛出的,而是在ArrayList继承的AbstractList父类中抛出的,ArrayList重写了父类的方法,虽然其中并没有抛出: java.lang.UnsupportedOperationException
但是查看了源码,就可以知道:父类抽象类:AbstractList的remove(int index)方法中,抛出了异常。
public E remove(int index) { throw new UnsupportedOperationException(); }
还有一种现象:就是我们删除数据的位置超过数组上限值,也抛出:java.lang.UnsupportedOperationException
public static void main(String[] args) { List alist=Arrays.asList(1,2,3,4,5,6,7,8,9,10); alist.remove(100); }
运行结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at com.xfwl.test.Test2.main(Test2.java:11)
分析说明:
可以看到,超过上限值,也会抛出父类方法中的异常。
总结一下:
首先ArrayList是子类,AbstractList是父类。
(1)当子类中因为超过上限,而抛出:throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 但是合格异常并没有被处理,会继续往上抛,就会抛到父类中去。而父类AbstractList的实现接口List和继承AbstractCollection类中都没有:
public E remove(int index)这个方法,换句话说就是, public E remove(int index)这个方法在AbstractList这里就终止了,也就抛出了AbstractList中的这个异常。
(2)当子类中因为地域下限时,由于没有异常捕获或者抛出处理,所以同样会到父类中捕获抛出异常。
(5)集合中是如何把数据传递给迭代器中的链表的呢?
分析JDK1.8的源码,可以知道:ArrayList中提供了,三个获取迭代器的方法,2个内置的具有继承关系的迭代器类。
三个获取迭代器的方法:
1 public ListIterator<E> listIterator(int index) {//【1】获取数组指定位置(不是索引值)之后的数组数据存放入迭代器链表中 2 if (index < 0 || index > size) 3 throw new IndexOutOfBoundsException("Index: "+index); 4 return new ListItr(index); 5 } 6 public ListIterator<E> listIterator() {//【2】默认的方法。获取所有的数组数据放入迭代器链表中 7 return new ListItr(0); 8 } 9 10 public Iterator<E> iterator() {//【3】默认方法。获取所有的数组数据放入迭代器链表中 11 return new Itr(); 12 } 13 //说明:【2】和【3】的区别是返回的类型不懂,Iterator是ListIterator的父类
2个内置的迭代器类:
private class Itr implements Iterator<E> {}
Itr类内部结构图:
1 private class Itr implements Iterator<E> { 2 int cursor; // index of next element to return 3 int lastRet = -1; // index of last element returned; -1 if no such 4 int expectedModCount = modCount; 5 6 public boolean hasNext() { 7 return cursor != size; 8 } 9 10 @SuppressWarnings("unchecked") 11 public E next() { 12 checkForComodification(); 13 int i = cursor; 14 if (i >= size) 15 throw new NoSuchElementException(); 16 Object[] elementData = ArrayList.this.elementData; 17 if (i >= elementData.length) 18 throw new ConcurrentModificationException(); 19 cursor = i + 1; 20 return (E) elementData[lastRet = i]; 21 } 22 23 public void remove() { 24 if (lastRet < 0) 25 throw new IllegalStateException(); 26 checkForComodification(); 27 28 try { 29 ArrayList.this.remove(lastRet); 30 cursor = lastRet; 31 lastRet = -1; 32 expectedModCount = modCount; 33 } catch (IndexOutOfBoundsException ex) { 34 throw new ConcurrentModificationException(); 35 } 36 } 37 38 @Override 39 @SuppressWarnings("unchecked") 40 public void forEachRemaining(Consumer<? super E> consumer) { 41 Objects.requireNonNull(consumer); 42 final int size = ArrayList.this.size; 43 int i = cursor; 44 if (i >= size) { 45 return; 46 } 47 final Object[] elementData = ArrayList.this.elementData; 48 if (i >= elementData.length) { 49 throw new ConcurrentModificationException(); 50 } 51 while (i != size && modCount == expectedModCount) { 52 consumer.accept((E) elementData[i++]); 53 } 54 // update once at end of iteration to reduce heap write traffic 55 cursor = i; 56 lastRet = i - 1; 57 checkForComodification(); 58 } 59 60 final void checkForComodification() { 61 if (modCount != expectedModCount) 62 throw new ConcurrentModificationException(); 63 } 64 }
private class ListItr extends Itr implements ListIterator<E> {}
ListItr类内部结构图:
1 private class ListItr extends Itr implements ListIterator<E> { 2 ListItr(int index) { 3 super(); 4 cursor = index; 5 } 6 7 public boolean hasPrevious() { 8 return cursor != 0; 9 } 10 11 public int nextIndex() { 12 return cursor; 13 } 14 15 public int previousIndex() { 16 return cursor - 1; 17 } 18 19 @SuppressWarnings("unchecked") 20 public E previous() { 21 checkForComodification(); 22 int i = cursor - 1; 23 if (i < 0) 24 throw new NoSuchElementException(); 25 Object[] elementData = ArrayList.this.elementData; 26 if (i >= elementData.length) 27 throw new ConcurrentModificationException(); 28 cursor = i; 29 return (E) elementData[lastRet = i]; 30 } 31 32 public void set(E e) { 33 if (lastRet < 0) 34 throw new IllegalStateException(); 35 checkForComodification(); 36 37 try { 38 ArrayList.this.set(lastRet, e); 39 } catch (IndexOutOfBoundsException ex) { 40 throw new ConcurrentModificationException(); 41 } 42 } 43 44 public void add(E e) { 45 checkForComodification(); 46 47 try { 48 int i = cursor; 49 ArrayList.this.add(i, e); 50 cursor = i + 1; 51 lastRet = -1; 52 expectedModCount = modCount; 53 } catch (IndexOutOfBoundsException ex) { 54 throw new ConcurrentModificationException(); 55 } 56 } 57 }
从代码中,我们可以看到,这两种迭代器,从根本上来说都是使用实现了 Iterator接口来存储数据,定位数据,移动数据。
关于链表的数据结构,以后会在算法章节做另做模拟、测试和分析。
好了,此篇到此结束了!